Sergey Bakotin
Sergey Bakotin

Reputation: 489

How to use 2 ForeignKey filters one by one in 1 view - Django?

Hello and thank your for your answer:

My Taks: Show article, show 3 questions (related to this article), show 3 answer for each queston (related to these questions). Like a coomon test page.

My models:

class Step(models.Model):  #Main article
    title = models.CharField(max_length=200)
    description = models.CharField(max_length=200)
    annotation = models.TextField()
    main_text = models.TextField()   

    def __str__(self):
        return self.title

class Question(models.Model): #Questios related to Article.
    step = models.ForeignKey(Step, on_delete=models.CASCADE)
    title = models.CharField(max_length=200, default = "pages")
    question_text = models.TextField()
    question_name = models.CharField(max_length=40, help_text="английские буквы", blank=True, null=True)

class Answer(models.Model): #Answers related to Questions
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.TextField()
    votes = models.IntegerField(default=0)
    answer_name = models.CharField(max_length=40, help_text="английские буквы", blank=True, null=True)

How it should works

I use identificator in url, to show django which article it should show. Also it helps me to filtrs questions for this article. And then i should filted answers for each question, i have got previously. There are many articles, questions and answers, so you can't use objects().all.

url(r'^question(?P<question_id>[0-9]+)$', 'bakot.views.question', name='question'), #urls.py

def question(request, question_id):
    stepfields = get_object_or_404(Step, id = question_id) #get an article
    questionship = Question.objects.filter(step_id = question_id) #get questions, related to this article.
    answership = questionship.prefetch_related().all #this is doesn't work. And i couldn't use coommon filter, as i don't know id for them. Or i could set ID and it will show the same answers for 3 questions.        
    context = {
        "stepfieldst" : stepfields,
        "questionship" : questionship,
        "answership" : answership,
    }
    return render(request, 'bakot/question.html', context)

How i show it in template: (the part with questions ans answers)

{% block question_area %}
  {% for question in questionship %}
  <div class="small-12 medium-12 large-12 test-remark">
    <legend><strong>{{ question.title }}&nbsp;</strong>{{ question.question_text }}</legend>

      <ul class="menu vertical">

        {% for answer in answership  %}
        <li>
          <ul class="menu test-answer-padding navigation_hover_link11">
            <li class="test-dot-padding"><input type="radio" name="{{ question.question_name }}" value="{{ answer.answer_name }}" id="pokemonRed" required></li>
            <li><label for="pokemonRed">{{ answer.choice_text }}</label>
          </ul>
        </li>

        {% endfor %}

      </ul>

  </div>
  {% endfor %}
{% endblock %}

Upvotes: 0

Views: 36

Answers (1)

Colton W
Colton W

Reputation: 51

There are a few things I would do here to provide you the best solution.

First, you don't need to include questionship and answership in your context. Your template can get them via stepfields.questions and question.answers.

Next, to limit your list to 3, I would implement a template filter. This could be done using slices, like this:

register = template.Library()

@register.filter
def limit_to_3(list, arg):
    return list[0:arg]

You could then, in your template, change your {% for %} loops to be this format:

{% for question in stepfieldst.questions|limit:3 %}
    {% for answer in question.answers|limit:3 %}
    {% endfor %}
{% endfor %}

Depending if your number of questions and answers per article are low enough that querying them all would be less burdensome than multiple queries, you could do something like this:

try:
    stepfieldst = Step.objects.select_related(questions__answers).filter(id = question_id)
except Step.DoesNotExist:
    raise Http404

This would select all related questions and answers in a single query.

Upvotes: 1

Related Questions