Roma
Roma

Reputation: 409

Django Views:Getting ListView inside Detailed View

I have the following setup. I have Teachers, which can have many Students. Both of them are Django Users. Students can leave reviews for Teachers. I'm building the Teacher Detail View. That is the url /teachers/1 where /teachers/ is the List View.

Now the problem:

I want all reviews, left by the user to be visible in the given teacher view. That would correspond to a 'ListView' within a DetailedView. Urls.py

urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>[0-9]+)/$', views.TeacherView.as_view(), name='detail'),
]

Models.py

class Teacher(models.Model):
    user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='Teacher')
    availability = models.BooleanField(default=False)


    def __str__(self):
        return self.user.username

class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='Student')
    teacher = models.OneToOneField(Teacher, on_delete=models.PROTECT, related_name='Student')
    reviewed = models.BooleanField(default=False)

    def __str__(self):
        return self.user.username

class Review(models.Model):
    teacher = models.OneToOneField(Teacher, on_delete=models.PROTECT, related_name='Teacher')
    student = models.OneToOneField(Student, on_delete=models.PROTECT, related_name='Student')
    star = models.IntegerField(default=5)
    body = models.TextField()

And finally the main problem - views.py

class IndexView(ListView):
    # context_object_name = 'latest_teacher_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Teacher.objects.all()[:5]


class TeacherView(generic.DetailView):
    model = Teacher

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super(TeacherView, self).get_context_data(**kwargs)
        # Add extra context from another model
        context['reviews'] = Review.objects.filter(teacher_pk=pk)
        return context

This doesn't work, it complains that pk is not defined. What it does in my head, is get the pk from URL, then finds all review objects where user.teacher.pk (or teacher.pk or teacher_pk) = pk.

I tried playing around with **kwags and replacing by pk, without success.

Also, as additional question I would like to display the average rating.

I'm thinking of rating = Review.objects.filter(teacher_pk=pk).aggregate(Avg('star')

Upvotes: 2

Views: 926

Answers (1)

Alasdair
Alasdair

Reputation: 308899

You can get the pk from self.kwargs:

context['reviews'] = Review.objects.filter(teacher_pk=self.kwargs['pk'])

Upvotes: 3

Related Questions