在外键对象中对字段进行django过滤

4 投票
4 回答
6578 浏览
提问于 2025-05-01 06:00

根据Django投票教程中的以下模型:

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently'


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

    def __str__(self):
        return self.choice_text

我想排除那些没有选项的题目,就像教程中建议的那样。我尝试过使用过滤器,但我搞不清楚怎么做。我试过:

def get_queryset(self):
    return Question.objects.filter(pub_date__lte=timezone.now(), choice__count__gt=0)

但是我得到了

Relation fields do not support nested lookups

我该如何过滤掉没有任何选项的题目呢?

暂无标签

4 个回答

0

我会把模型改成像这样的:

class Question(models.Model):
    choices = models.ManyToManyField('Choice')
    ...

class Choice(models.Model):
    question = models.ForeignKey(Question)
    ...

查询会像这样:

questions = Question.objects.annotate(num_of_choices=Count('choices')).filter(pub_date__lte=timezone.now(), num_of_choices=0)
1

你需要用 choice__isnull=False 来替代像计数那样的方法。

return Question.objects.filter(pub_date__lte=timezone.now(), 
                               choice__isnull=False)

注意,你可能会得到重复的记录,可以使用 .distinct() 来去重。

2

使用 choice__isnull=True,其中 choice 是你定义的相关名称。

def get_queryset(self):
    return Question.objects.filter(pub_date__lte=timezone.now(), choice__isnull=False)
8

你也可以像下面这样使用

from django.db.models import Count

......

def get_queryset(self):
    return Question.objects.annotate(num_choice=Count('choice')).filter(pub_date__lte=timezone.now(), num_choice=0)

撰写回答