问题
I have two models: call them questions and answers:
class FacetQuestion(models.Model):
the_question = models.CharField(max_length=50)
class FacetAnswer(models.Model):
question = models.ForeignKey(FacetQuestion)
display_order = models.SmallIntegerField()
the_answer = models.CharField(max_length=1024)
I'd like to present all the questions and answers in one list, with the questions and answers ordered per my choosing:
Q1
A1
A2
A3
Q2
A10
A9
A4
Without creating n+1 database queries or creating silly looking templates. That's an easy join for a database guy like myself, but Toto informs us we're not in SQL land anymore:
select title_short,answer_note from coat_facetquestion
join coat_facetanswer on (coat_facetanswer.question_id=coat_facetquestion.id)
order by coat_facetquestion.id,coat_facetanswer.display_order;
What's the best way in Django, and what would the template look like?
<ul>
{% for q in questions %}
<li>{{ q.the_question }}</li>
{% for a in q.FacetAnswers_set.all %}
<li>{{ q.the_answer }}</li>
{% endfor %}
{% endfor %}
</ul>
I see an older module that's a bit on track at django-batch-select. There's also select_related() which feels like it must be the answer, but if so the documentation is not quite making that clear.
回答1:
You can use FacetQuestion.objects.select_related('facetanswer_set').all()
Also have a look at setdefault(). It's a Python command that lets you build a nested dict structure. You query all questions and all answers and then build the structure you need in Python.
回答2:
There is an excellent guide here:
http://blog.roseman.org.uk/2010/01/11/django-patterns-part-2-efficient-reverse-lookups/
that describes exactly how to solve this problem.
Another approach is to use:
Django-selectreverse
which is a generic approach to utilizing what was described in the guide above.
回答3:
I can only answer you one part of the question.
select_related()
is probably not what you are looking for. It will select you the "1-side" of a 1:n relationship. This would allow you to select all answers nd also fetch the related question for each answer in one go.
However, you can filter the query using properties of the related entity like this:
FacetAnswer.objects.filter( question__property = 'some_value' ).select_related()
Still, your QuerySet will be based on the Answer-Model, so you can only iterate for a in answers
.
回答4:
Based on searching other stack exchange answers: for dealing with the hierarchical data, the best seems to be http://django-mptt.github.com/django-mptt/
For simply reducing the number of queries select_related() is a great help.
For displaying the hierarchical result I have not yet found much.
来源:https://stackoverflow.com/questions/9442553/avoiding-n1-queries-to-query-model-plus-all-foreignkey-associations