I am relatively new to Django (v=2.1). I am stuck since few days searching for a solution to this problem which I think is fairly easy but, despite reading many posts here and elsewhere, did not manage to solve it yet. I have two models: Teacher and Assignment. Very simplified:
models.py
class Teacher(models.Model):
name = models.CharField(max_length=200)
class Assignment(models.Model):
title = models.CharField(max_length=200)
teacher = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True)
I have a (working) site with a list of Assignments of teacher nr. x which I produced with a generic DetailView function and some of the code looks like this:
assignments_list.html
{% for assignment in teacher.assignment_set.all %}
...
<a href="{% url 'assignment-detail' pk1=assignment.teacher.pk pk2=assignment.pk %}">{{assignment.title}}</a>
...
{% endfor %}
When I click on the assignment.title I want to get the detail page of the assignment of this specific teacher. I use this url conf:
urls.py
urlpatterns += [path('teacher/<int:pk1>/assignment/<int:pk2>/', views.AssignmentDetailView.as_view(), name = 'assignment-detail')]
and I use this view function (I tried several variants):
views.py
from .models import Teacher, Assignment
from django.views import generic
class AssignmentDetailView(generic.DetailView):
model = Assignment
template_name = 'assignment_detail.html'
def get_queryset(self, **kwargs):
queryset = super(AssignmentDetailView, self).get_queryset()
return queryset.filter(teacher_id=self.kwargs['pk1'], pk=self.kwargs['pk2'])
I'm trying to pass the two parameters (pk1 and pk2) that are in the context of the page (that contains the list of assignments). If I click on the link (assignment.title) I do see a url with the correct numbers for pk1 and pk2 (I see that in the url address bar, eg http://localhost:8000/teacher/2/assignment/4 ). But no page is displayed. By tweaking a bit things I get different errors:
My questions:
Thank you so much for any advice.
Your view only returns a query set, not an actual object (which a detail view needs). If you are just trying to get the assignment object you don't even need to pass the teacher_id. On your first page you list all the assignments from a single teacher, you just need to pass the assignment.pk to the detail view.
path('assignment/<int:pk>/', views.AssignmentDetailView.as_view(), name='assignment-detail')
If you create your url like above, the detail view handles getting the object by the pk. If you want to have the teacher id in your url you can still do that but call it something like <int:teacher_id>
. The detailview will by default only look for a 'pk' in the kwargs, so ignore the teacher_id
Thank you all so much for the fast reply (I did not expect that!) Sorry if I do not react to all comments but I appreciate every help.
I worked on it again and now understand that queryset returns a set and not a single model instance (for which I better use 'get'). I changed as follows and now it works:
assignments_list.html
<a href="{% url 'assignment-detail' pk=assignment.teacher.pk pk1=assignment.pk %}">
views.py
class AssignmentDetailView(generic.DetailView):
model = Assignment
template_name = 'assignment_detail.html'
def get_object(self, **kwargs):
assignment = Assignment.objects.get(id=self.kwargs['pk1'])
return assignment
def get_context_data(self, **kwargs):
context = super(AssignmentDetailView, self).get_context_data(**kwargs)
context['teacher'] = Teacher.objects.get(id=self.kwargs['pk'])
return context
Now it works. I needed both pk numbers because the header on 'assignment_detail.html' is an {% include 'header-teacher.html' %}
that contains <a href="{% url 'teacher-profile' teacher.pk %}">
. Now I have passed two values from the url: pk1 for retrieving the correct assignment and pk to provide the (extra) correct context (that delivers the teacher pk).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.