Search code examples
pythondjangodjango-modelsdjango-queryset

How to return a QuerySet of 2 models via reverse ForeignKey lookup in Django?


I have "Parameter" and "ParameterChoice" models where I define multiple choices for each parameter. The end goal is to have some sort of assessment where I have a list of parameters where each parameter has a specific fixed set of choices available for selection from a dropdown list within the HTML template.

I want to somehow pass one or two querysets to the template where I will render a table of all parameters and available choices next to it. Unfortunately, I really struggle to come up with logic in Django on how to achieve this. Ideally, result would look like this:

Parameters Choices
Param1 ChoiceA ChoiceB ChoiceC
Param2 ChoiceY ChoiceZ

How can I make this happen without a raw SQL query?

Current setup:

models.py

class Parameter(models.Model):
    text = models.CharField(blank=False, null=False, max_length=200)

class ParameterChoices(models.Model):
    text = models.CharField(blank=False, null=False, max_length=200)
    parameter = models.ForeignKey(Parameter, related_name='parameterchoices', on_delete=models.CASCADE, blank=False, null=False)

views.py

def parameters(request):
    params = Parameter.objects.all()
    param_choices = ParameterChoices.objects.all()
    context = {
        'parameters': params,
        'parameter_choices': param_choices,
    }
    return render(request, 'questionnaire/parameters.html', context)

Solution

  • If I understand your question correctly, you want to have params mapped to their choices. to do so pass the context like this.

    def parameters(request):
        params = Parameter.objects.all().prefetch_related("parameterchoices")
        all_params = [
           {
              'parameter': param,
              'choices': param.parameterchoices.all()
           }  for param in params
        ]
    
        context = {
          "params": all_params
        }
        return render(request, 'questionnaire/parameters.html', context)
    
    

    So in the template, you can loop over on params and render their related choices.

    Note prefetch_related is optional. its their to boost performance and avoiding N+1 query problem.