【问题标题】:Django: Create QuerySet baed on number of one-to-many obejcts in DBDjango:根据数据库中一对多对象的数量创建查询集
【发布时间】:2021-08-04 11:16:07
【问题描述】:

在 Django 中,如果我有两个模型 Question 和 Choice 具有一对多关系,我如何过滤 Question 对象的 Manager 以创建仅包含具有一个或多个 Choices 的 QuerySet?

当前代码如下,它指的是根据特定条件显示问题列表的视图:

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.filter(
            pub_date__lte=timezone.now()
        ).order_by('-pub_date')[:5]

视图显示最近的五个问题,它们的 pub_date 字段不在未来时间。我知道我可以通过以下方式访问我需要的值:

questions = Question.objects.filter(pub_date__lte=timezone.now()
for q in questions:
    number_of_choices = q.choice_set.count()

但我需要 get_queryset 方法在访问choice_set 时返回一个QuerySet 需要执行查询并从结果中提取问题。

那么,如何根据其choice_set 属性过滤该QuerySet?

(这是Django网站上教程第5部分的“更多测试的想法”部分提出的挑战)

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    如果我明白你想要什么,你想检查 Question 是否有选择。

    如果我是你,我会使用exists()

    代码如下:

    # models.py
    
    class Question(models.Model):
        text = models.CharField()
    
    class Choice(models.Model):
        question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="choices")
    
    # views.py
    
    def test_question_has_choices(question):
        if question.choices.exists():
            return "Question has choices."
        else:
            return "Question has no choices."
    

    如果问题有选择,test_question_has_choices 将返回“问题有选择。”。

    如果没有,将返回“问题没有选择。”

    【讨论】:

    • 和我的意思差不多,但不完全一样。我正在编写一个将返回问题列表的视图。我会用更多细节更新我的问题。
    【解决方案2】:

    以下将起作用,它应该是与 Django 一起使用的惯用方法:

    from django.db.models import Count
    from .models import Question
    
    class IndexView(generic.ListView):
        template_name = 'polls/index.html'
        context_object_name = 'latest_question_list'
    
        def get_queryset(self):
            """
            Return the last five published questions (not including those
            set to be published in the future or questions without choices).
            """
            return Question.objects.annotate(
                choice_count=Count('choice')
            ).filter(
                pub_date__lte=timezone.now(),
                choice_count__gt=0
            ).distinct().order_by('-pub_date')[:5]
    

    这是对提供此解决方案的先前答案的编辑,我不相信其效率。

    def get_queryset(self):
        return Question.objects.filter(
            pub_date__lte=timezone.now(),
            choice__id__gt=0
        ).distinct().order_by('-pub_date')[:5]
    

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 2011-06-28
      • 2016-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-08
      • 2014-02-22
      • 1970-01-01
      相关资源
      最近更新 更多