如何在django DetailView中命令嵌套模型

时间:2017-04-03 23:46:12

标签: python django

我正在使用Django 1.10

我通过制作调查计划学习Django

我制作了三个模型,调查包括问题,问题包括选择

Models.py

from django.db import models

class Survey(models.Model):
    title = models.CharField(max_length = 200)
    description = models.TextField()
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.title

class Question(models.Model):
    survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
    question_text = models.CharField(max_length=200)

    def __str__(self):
        return "%s : %s" % (self.survey, self.question_text)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return "%s - %s" % (self.question, self.choice_text)

我想通过投票显示我的结果页面,但现在,我只显示未订购的结果页面。

我想我必须使用queryset或额外的上下文修改我的views.py. 但我不知道如何使用。

以下是我的观点和模板。

views.py

class SurveyResultsView(DetailView):
    model = Survey
    template_name = 'survey/results.html'

results.html

{% extends 'survey/base.html' %}
{% block content %}

<div class="survey-info-container">
  <h1>Results of {{survey.title}}</h1>
  <p>{{survey.description}}</p>
  <p>{{survey.pub_date}}</p>
</div>

<div class="result-container">
  {% for question in survey.question_set.all %}
  <p>
    <h3>{{question.question_text}}</h3>
    <ul>
        {% for choice in question.choice_set.all %}
          <li>{{choice.choice_text}} -- {{choice.votes}} votes </li>
        {% endfor %}
    </ul> 
  </p>
  {% endfor %}
</div>
{% endblock content %}

感谢您阅读。

1 个答案:

答案 0 :(得分:0)

我可以提出三种不同的方法来实现这一目标。

按模板排序

第一个,最明显的一个是在模板中获取choice对象时对它们进行排序。您可以使用您应用的dictsort过滤器(Docs)执行此操作,如下所示。

{% for choice in question.choice_set.all|dictsort:"votes" %}
    <li>{{choice.choice_text}} -- {{choice.votes}} votes </li>
{% endfor %}

注意,还有一个dictsortreversedDocs)过滤器,它按相反的顺序排列对象。

模型

上的功能

另一种方法是在Question模型上定义一个函数,该函数以您希望的排序顺序返回条目,然后在模板中调用question.choice_set.all()而不是调用而不是功能。

示例:

class Question(models.Model):
    #... 
    def choice_set_sorted(self):
        # Can set .order_by('-votes') to reverse order
        return self.choice_set.all().order_by('votes')

模板:

{% for choice in question.choice_set_sorted %}
    <li>{{choice.choice_text}} -- {{choice.votes}} votes </li>
{% endfor %}

设置元类

第三个选项是在模型上设置默认排序。如果您始终希望Choicevotes订购,这可能是一个好主意。

您可以通过在模型中设置Meta类并将ordering属性设置为您要按其排序的字段(Docs)来执行此操作。

所以你实现这个的方式是:

class Choice(models.Model):
    #...
    class Meta:
        ordering = ['votes']

////