pass two of pk into url - python

If the 'school year' value is changed, 404 does not appear.
I want data to be displayed only when both 'school_year' and 'pk' have the right values in url.
for example
If you have data that (School_Year = 2020, pk = 33)
when you enter url https://190.0.1/190/190/33 and https://190.0.1/190/whatthell/33
Both are the same results.
However, I would like to display the result only when both values are correct.
i really dont know if i explained correctly, thanks.
view.py
class StudentDetail(DetailView,FormView):
model = Student
template_name = 'student/member.html'
context_object_name = 'student'
form_class = AddConsultation
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['pk'] = Student.objects.filter(pk=self.kwargs.get('pk'))
return context
url.py
path('student/<school_year>/<pk>/', views.StudentDetail.as_view(), name='student_detail'),
html link
<a href='{% url 'student_detail' student.school_year student.pk %}'>
models.py
class Student(models.Model):
school_year = models.CharField(
max_length=10,
choices=SCHOOL_YEAR_CHOICES,
default='2021N',
verbose_name='school year'
)
... etc

I would remove get_context_data and override get_object using get_object_or_404:
class StudentDetail(DetailView, FormClass):
model = Student
template_name = 'student/member.html'
context_object_name = 'student'
form_class = AddConsultation
def get_object(self, queryset=None):
return get_object_or_404(Student, pk=self.kwargs['pk'], school_year=self.kwargs['school_year'])
Other solution may be:
class StudentDetail(DetailView, FormClass):
model = Student
template_name = 'student/member.html'
context_object_name = 'student'
form_class = AddConsultation
slug_field = 'school_year'
slug_url_kwarg = 'school_year'
query_pk_and_slug = True
but I find the first one less magic :)

Related

KeyError at /x/x/ 'pk' django

I'm trying to get a DetailView's model's pk in a variable in the get_context_data but I keep getting the error KeyError at /x/x/ 'pk'.
views.py
class MangaView(DetailView):
model = Manga
template_name = 'mangas/manga.html'
context_object_name = 'manga'
slug_field = 'manga_slug'
slug_url_kwarg = 'manga_slug'
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
manga = get_object_or_404(Manga, id=self.kwargs['pk']) # error line
favorited = False
latered = False
...
return data
urls.py
urlpatterns = [
path('mangas/', MangasHomeView.as_view(), name='mangas-home'),
path('manga/<slug:manga_slug>/', MangaView.as_view(), name='manga'),
...
]
The error you are seeing is caused by trying to access the pk value through self.kwargs, when in fact your view is using a slug field and slug URL parameter.
Try to use self.get_object() as it gives you current instance in DetailView whether it is pk or slug so:
class MangaView(DetailView):
model = Manga
template_name = 'mangas/manga.html'
context_object_name = 'manga'
slug_field = 'manga_slug'
slug_url_kwarg = 'manga_slug'
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
manga = self.get_object()
favorited = False
latered = False
...
return data

Django - Pass a dictionary to template through the get_queryset function of a class based view

Is there a way to return a dictionary through the get_queryset function of a class based view in Django? I want to pass the array tickets and the string email to my template, but I am only able to pass tickets right now.
Content of views.py:
class UserTicketListView(ListView):
model = Ticket
template_name = 'ticket_system/user_tickets.html'
context_object_name = 'tickets'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
email = User.objects.get(username=user).email
return Ticket.objects.filter(author=user).order_by('-date_posted')
class UserTicketListView(ListView):
model = Ticket
template_name = 'ticket_system/user_tickets.html'
context_object_name = 'tickets'
ordering = ['-date_posted']
paginate_by = 5
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
queryset = self.get_queryset()
user = get_object_or_404(User, username=self.kwargs.get('username'))
email = User.objects.get(username=user).email
queryset = queryset.filter(author=user).order_by('-date_posted')
context['user'] = user
context['email'] = email
return context

Generic detail view PostDetailView must be called with either an object pk or a slug in the URLconf

I used get_absolute_url in my model but when I am browsed my post link I got this type error
AttributeError at /blog/details/Hello-World1/
Generic detail view PostDetailView must be called with either an object pk or a slug in the URLconf.
I would like to create link this link /Hello-World1/ (mix with title and pk id)
Models.py
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, models.SET_NULL, null=True, blank=True,)
title = models.CharField(max_length=200)
content = models.TextField()
tags = models.ManyToManyField(Tag)
created_at=models.DateTimeField(auto_now_add=True)
updated_at=models.DateTimeField(auto_now=True)
def get_absolute_url(self):
title = self.title.replace(" ", "-")
return reverse('blog:post_details', args=[title+str(self.id)])
views.py
class PostDetailView(DetailView):
model = Post
template_name = 'blogs/blog_details.html'
urls.py
path('details/<str:new_str>/', PostDetailView.as_view(), name="post_details"),
Your url should have pk arg instead of new_str
path('details/<int:pk>/', PostDetailView.as_view(), name="post_details"),
You need to rewrite get_object
view.py
class PostDetailView(DetailView):
model = Post
template_name = 'blogs/blog_details.html'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
new_str = self.kwargs.get('new_str') or self.request.GET.get('new_str') or None
queryset = queryset.filter(pk=new_str)
obj = queryset.get()
return obj
see http://www.chenxm.cc/article/1143.html
view.py
class PostDetailView(DetailView):
model = Post
template_name = 'blogs/blog_details.html'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
new_str = self.kwargs.get('new_str') or self.request.GET.get('new_str') or None
queryset = queryset.filter(pk=new_str)
obj = queryset.get()
return obj
see http://www.chenxm.cc/article/1143.html

How to pass data from SelectDateWidget to view and url

I have a problem how to pass selected data from SelectDateWidget to view and to url.
Now I have the hardcoded data get_success_url in the digest, after the "submit" on the form.
For the SelectDateWidget help, I want to select the month and year for which I want to show selected events.
Here is my form:
class BookingForm(forms.ModelForm):
date_start = forms.DateField(widget=SelectDateWidget(years=range(1980, 2018)))
class Meta:
model = Booking
fields = ('date_start', )
widgets = {'date_start': SelectDateWidget()}
This is my view, where I have hardcoded value for success url:
class BookingListView(ListView, FormView):
model = models.Booking
form_class = BookingForm
queryset = models.Booking.objects.all() # order_by('-date_start')
paginate_by = 80
template_name = 'events/archive_list.html'
context_object_name = 'object_list'
date_field = 'date_start'
allow_future = True
def get_context_data(self, **kwargs):
context = super(BookingListView, self).get_context_data(**kwargs)
context['mode'] = 'archive'
context['form'] = BookingForm()
return context
def get_success_url(self):
return reverse('archive:archive_month_numeric', kwargs={'year': 2014, 'month': 10})
My url to page where I have events in selected date:
url(r'^/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$', views.ArticleMonthArchiveView.as_view(month_format='%m'), name="archive_month_numeric"),

Django: How do you associate an Object_PK in the URL to the Foreign_Key relation field when creating a new object?

I am building an FAQ system. The models extend from Topic -> Section -> Article. When creating a new Article the User will select a Topic then a Section then the create Article button.
The url will look something like //mysite.org/Topic_PK/Section_PK/Article_Create
In Django it should look like this:
url(r'^ironfaq/(?P<pk>\d+)/(?P<pk>\d+)/article$', ArticleCreateView.as_view(), name=’article-create’)
What I am looking to do is to associate the Section_PK to the Article when the user submits the Article. I have the Section_PK in the URL I need help to figure out how to use it to do this.
Alternatively with this set up I can have a form rendered with a choice selection from the Section_FK in the Articles Model. If when creating the Article upon rendering the template if I could limit the Section choices by the Topic in the form.py this will also work for my needs
The url will look something like //mysite.org/Topic_PK/article/create
In Django the url should look like this:
url(r'^ironfaq/(?P<pk>\d+)/article/create$', ArticleCreateView.as_view(), name=’article-create’)
Both these methods require the Passing of the Topic or Section PK to the view or form thru the URL. If there is a better way to do this I am open to other suggestions.
In Django I have the following Models
class Topic(Audit):
name = models.CharField(max_length=255)
sort = models.SmallIntegerField()
slug = models.SlugField()
class Meta:
verbose_name_plural = "topics"
def __str__(self):
return self.name
def get_absolute_url(self):
return ('faq-topic-detail',(), {'slug': self.slug})
class Section(Audit):
name = models.CharField(max_length=255)
sort = models.SmallIntegerField()
slug = models.SlugField()
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "sections"
def __str__(self):
return self.name
def get_absolute_url(self):
return ('faq-section-detail',(), {'topic__slug': self.topic.slug,
'slug': self.slug})
class Article(Audit):
title = models.CharField(max_length=255)
sort = models.SmallIntegerField()
slug = models.SlugField()
section = models.ForeignKey(Section,on_delete=models.CASCADE)
answer = models.TextField()
vote_up = models.IntegerField()
vote_down = models.IntegerField()
view_count = models.IntegerField(default=0)
class Meta:
verbose_name_plural = "articles"
def __str__(self):
return self.title
def total_votes(self):
return self.vote_up + self.vote_down
def percent_yes(self):
return (float(self.vote_up) / self.total_votes()) * 100
def get_absolute_url(self):
return ('faq-article-detail',(), {'topic__slug': self.section.topic.slug,
'section__slug': self.section.slug, 'slug': self.slug})
Mysite Forms
class CreateArticleForm(forms.ModelForm):
class Meta:
model = Article
widgets = {
'answer': forms.Textarea(attrs={'data-provide': 'markdown', 'data-iconlibrary': 'fa'}),
}
fields = ('title','section','answer')
Mysite Views
class TopicCreateView(CreateView):
model = Topic
fields = ['name']
template_name = "faq/form_create.html"
success_url = "/ironfaq"
def form_valid(self, form):
topic = form.save(commit=False)
activity_user = self.request.user.username
activity_date = datetime.datetime.now()
topic.save()
return super(TopicCreateView,self).form_valid(form)
class SectionCreateView(CreateView):
model = Section
fields = ['name', 'topic']
template_name = "faq/form_create.html"
def form_valid(self, form):
section = form.save(commit=False)
activity_user = self.request.user.username
activity_date = datetime.datetime.now()
section.save()
self.success_url = "/ironfaq/%s/%s" % (section.topic.slug,section.slug)
return super(SectionCreateView,self).form_valid(form)
class ArticleCreateView(CreateView):
model = Article
form_class = CreateArticleForm
template_name = "faq/form_create.html"
def form_valid(self, form):
article = form.save(commit=False)
activity_user = self.request.user.username
activity_date = datetime.datetime.now()
article.save()
self.success_url = "/ironfaq/%s/%s/%s" % (article.section.topic.slug,article.section.slug,article.slug)
return super(ArticleCreateView,self).form_valid(form)
Let's say that you have this url
url(r'^ironfaq/(?P<topic_pk>\d+)/article/create$', ArticleCreateView.as_view(), name=’article-create’)
Where topic_pk will be pk of topic you want to be associated with your Article.
Then you just need to retrieve it in view. And this is done like this
class ArticleCreateView(CreateView):
model = Article
form_class = CreateArticleForm
template_name = "faq/form_create.html"
def form_valid(self, form):
article = form.save(commit=False)
# what are this variables for?
activity_user = self.request.user.username
activity_date = datetime.datetime.now()
# here we are getting 'topic_pk' from self.kwargs
article.topic_id = self.kwargs['topic_pk']
article.save()
self.success_url = "/ironfaq/%s/%s/%s" % (article.section.topic.slug,article.section.slug,article.slug)
return super(ArticleCreateView,self).form_valid(form)
All url params are stored in self.args and self.kwargs. Our topic_pk is named parameter and thats why we can get it by doing self.kwargs['topic_pk']
But be sure to validate existence of Topic with such pk before assigning it to your Article

Categories

Resources