[英]Check queryset is empty in Django
假设我有一段代码,例如:
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
all_entries = Choice.objects.all()
if not all_entries:
return Question.objects.filter(pub_date__lte=timezone.now())
我试图从一个问题中获取所有选择,如果没有可用的返回404。 但是我只设法实现了其中一部分并得到了错误:
'NoneType'对象没有属性'filter'
这是从Django教程的最底部提到的
例如,无选择地在网站上发布问题是很愚蠢的。 因此,我们的观点可以对此进行检查,并排除此类问题。
我要去哪里错了?
编辑:
我将引用“ all_entries”的代码更改为:
all_entries = Choice.objects.all().count()
if all_entries > 0:
return Question.objects.filter(pub_date__lte=timezone.now())
但这只是返回所有问题,无论他们是否有选择...
型号
from django.db import models
import datetime
from django.utils import timezone
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self): # __unicode__ on Python 2
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): # __unicode__ on Python 2
return self.choice_text
编辑cms_mgr
基本上,我想检查与指定问题相关的选项数量是否为空。 当我转到此链接时http://127.0.0.1:8000/polls/3/
我想从ID('3')中获取问题,并检查其包含的选择数量。
当且仅当它们具有相关选择时,获取所有问题的一种方法是获取Choices
列表,而不是问题,然后根据这些问题评估您的查询。 例如:
Question.objects.filter(pk__in=[x.question.pk for x in Choice.objects.all()])
方括号内的位是列表理解 。 列表推导非常有用,并且值得了解。 在列表上方的代码中,理解力将首先评估。 基本上说的是“对于Choice.objects.all()
每个x
,将x.pk
放入此列表中”。 然后查询集将返回存在至少一个相关Choice
每个Question
。
如果您想要的是每个Question
的Choices
,那么它们已经可供您使用。 对于Question
任何实例,我们将其称为q
,您可以使用q.choice_set.all()
获得与之关联的Choices
,如果不存在则返回空值。
要实现:首先更改您的DetailView
的名称,以避免与通用名称混淆。 我们称它为QuestionDetailView
。 添加一个context_object_name
以使您的模板以后更易读。 不要修改默认查询集以排除未发布的问题,因为正确的方法是使用模型管理器 。
class QuestionDetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
context_object_name = 'question'
在您用于该视图的模板中,问题的相关选择已经可以通过{% for choice in question.choice_set.all %}
。 这个question
之所以被称为,是因为我们给它提供了一个context_object_name
因此您可以使用任何您喜欢的名称。 请注意,模板中的all
都不需要()
。
如果您需要对选择进行其他处理,然后再将其返回到模板,则可以在视图中进行选择。 因此,在您的QuestionDetailView
您可以添加:
def get_context_data(self, **kwargs):
# call the base implementation to get original context
context = super(DetailView, self).get_context_data(**kwargs)
context['choices'] = self.object.choice_set.all() # your question's choice set, to manipulate
# as you see fit
return context
我会解释这里发生了什么。 这为视图返回的模板添加了额外的上下文。 我编写的代码将仅返回所有问题的选择,因此不会添加到已有的内容中,但是您可以执行自己喜欢的其他任何操作。 然后,修改后的选择集将在您的模板中作为choices
可用,因此您可以在{% for choice in choices %}
执行{% for choice in choices %}
。
无论采用哪种方式选择一个空的选择集都是可能的,并且可以轻松地迎合它(例如,模板中的{% if choices %}
或{% if question.choice_set.count %}
)。 您可能想要比404更优雅地处理任何空查询集,因为您实际上并不希望将用户定向到错误页面以得到可预测的结果,例如空查询集。
如果all_entries 不为空,则不返回任何内容。 如果函数未明确返回值,则Python返回None
。
您尝试做的事情并不像看起来那样简单。 您必须按问题的查询选项集的数量来过滤问题,而不要检查选择项是否存在,然后返回问题。
您应该查看其他答案 ,看看如何通过注释来完成。
也许值得一提的是本系列后面的教程第7部分 ,从根本上提示了处理以下问题的正确方法。
例如,无选择地在网站上发布问题是很愚蠢的。 因此,我们的观点可以对此进行检查,并排除此类问题。
我认为解决此问题的最佳方法是首先避免创建“问题无选择”(假设没有人直接修改数据库)。 本教程教您如何修改管理站点页面,在该页面上,我们仅应允许管理员添加至少具有2个选择的Question。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.