Search code examples
djangodjango-modelsdjango-views

How to combine multiple querysets in a Django view?


I am developing an exam page, where the user can take an exam several times and the results will be saved in the Score model. Currently I can store the results of the logged in user, but I need it to show me the entire list of scores they have achieved when I enter the details of each user.

I have access to the list of users with the userList view, and I can access the details of each user with the userDetail view, but I want to know if there is a way to show all the scores of the selected user in the same details view.

Here's de Score model: MODELS

class Score(models.Model):
#The user field is a foreign key from User(AbstractUser)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    score = models.IntegerField(default=0)
    evaluation_date = models.DateTimeField()

These are the views I'm using for the user list, user detail and saving the new score: VIEWS

class userList(LoginRequiredMixin, ListView):
    template_name = "users/list.html"
    queryset = User.objects.all()
    context_object_name = "users"

class userDetail(LoginRequiredMixin, DetailView):
    template_name = "users/detail.html"
    queryset = User.objects.all()
    context_object_name = "user"

@csrf_protect
def send(request):
    if request.method == 'POST':
        if 'answers' in request.POST:
            answers = request.POST['answers']
            time = datetime.datetime.now()
            current_user = request.user
            Note.objects.create(
                user = current_user,
                score = answers,
                evaluation_date = time
            )
            return HttpResponse('Successful')
    return HttpResponse('FAIL!')

And these are the URLs from user list and user detail: URL

urlpatterns = [
    path('list/', userList.as_view(), name='list'),
    path('list/<int:pk>/', userDetail.as_view(), name='detail')
]

I tried sending multiple contexts as follows:

class userDetail(LoginRequiredMixin, DetailView):
    context_object_name = "data"
    template_name = "users/detail.html"

    def get_queryset(self):
        myset = {
            "user": User.objects.all(),
            "score": Score.objects.all(),
            .
            .
            .
        }
        return myset

But I only got an error with the primary key

<int:pk>

Solution

  • In a view that has access to user object, you can do user.score_set.all() to access all the scores for that particular user. In your userDetail view:

    class userDetail(LoginRequiredMixin, DetailView):
        ... 
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context["user_scores"] = self.object.score_set.all()
            return context
    
    

    user_scores will thus be available in the user detail template.

    Side note
    Python's best practices say class names in Python should be in PascalCase, not camelCase. So, userDetail should really be UserDetail.