Django中查询查询器是空的 [英] Check queryset is empty in Django
问题描述
class DetailView(generic.DetailView):
model =
template_name ='polls / detail.html'
def get_queryset(self):
排除任何尚未发布的问题
all_entries = Choice.objects.all()
如果不是all_entries:
return Question.objects.filter(pub_date__lte = timezone.now())
我正在尝试从问题中获取所有选项,如果没有可用,返回404 。然而,我只是设法实现其中的一部分,并得到错误:
'NoneType'对象没有属性'filter'
这是从 Django教程,它提及
例如,可以发布问题的愚蠢在没有选择的网站上。所以,我们的意见可以检查,排除这些问题。
我在哪里出错?
编辑: / strong>
我更改了引用all_entries的代码:
all_entries = Choice.objects.all()。count()
如果all_entries> 0:
return Question.objects.filter(pub_date__lte = timezone.now())
但是这只是返回所有问题,无论他们有选择吗?
Models.py
$从django.db导入模型
import datetime
从django.utils导入时区
class问题(模型)b $ b
模型)
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()
现在返回 - 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 ='最近发布?'
class Cho ice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length = 200)
vote = 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')获取问题并检查它包含的选择数量。
只有在有相关选择的情况下,获取所有问题的一种方法是获取选择
的列表,而不是问题,然后评估您的查询。例如:
Question.objects.filter(pk__in = [x.question.pk for x in Choice.objects.all( )])
如果你想要的是每个问题
的选项
的查询,那么他们已经可供你使用对于问题
的任何实例,我们将称为我们的 q
,您可以获取其相关联的选择
与 q.choice_set.all()
,如果没有,将返回空。
要实现:首先更改您的 DetailView
的名称,以避免与通用的名称混淆。让我们称之为 QuestionDetailView
。添加一个 context_object_name
以使您的模板更容易阅读。不要修改默认的查询器来排除未发布的问题,因为正确的方法是使用模特经理。
class QuestionDetailView(generic.DetailView):
model =问题
template_name ='polls / detail.html'
context_object_name ='question'
在该视图的模板中,问题的相关选择已经可用于您,例如 {%for question.choice_set.all%}
。调用问题
,因为我们给它一个 context_object_name
,所以你可以使用任何你喜欢的名字。请注意,模板中全部
之后,不需要()
。
如果您需要在将其返回到模板之前先做其他的选择,那么可以在视图中执行此操作。因此,在您的 QuestionDetailView
中,您可以添加:
def get_context_data ,** kwargs):
#调用基本实现以获取原始上下文
context = super(DetailView,self).get_context_data(** kwargs)
上下文['choices'] = self .object.choice_set.all()#你的问题的选择集,要操作
#,你看到合适
返回上下文
我会解释这里发生了什么。这是添加额外的上下文到视图将返回为您的模板消费。我写的代码只是返回所有问题的选择,所以不会添加到已经存在的内容,但是您可以执行任何其他您需要的操作。修改后的选择集将在您的模板中以选项
的形式提供,因此您可以在选择中选择 {%选择%}
无论你选择什么方式,您都可以选择一个空白的选项,您可以轻松满足( {%if choices%}
或 {%if question.choice_set.count%}
,例如)。您可能希望处理比404更优雅的任何空查询器,因为您不希望用户被引导到错误页面以获得可预测的结果,例如空查询器。
Say I had a piece of code like:
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())
I am trying to get all the choices from a question, and return a 404 if there are none available. However I have only managed to implement part of it and get the error:
'NoneType' object has no attribute 'filter'
This is taken from the very bottom of the Django tutorial where it mentions
For example, it’s silly that Questions can be published on the site that have no Choices. So, our views could check for this, and exclude such Questions.
Where am I going wrong?
EDIT:
I changed the code referencing "all_entries" with:
all_entries = Choice.objects.all().count()
if all_entries > 0:
return Question.objects.filter(pub_date__lte=timezone.now())
but that simply returns all questions, whether they have choices or not...
Models.py
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
EDIT For cms_mgr
Basically I want to check that the number of choices associated with the specified question is empty. When I go to this link - http://127.0.0.1:8000/polls/3/
I want to get the question from the id ('3') and check the number of choices it contains.
One way to approach getting all questions if and only if they have related choices is to get a list of Choices
rather than questions then evaluate your query against those. For example:
Question.objects.filter(pk__in=[x.question.pk for x in Choice.objects.all()])
The bit inside the square brackets is a list comprehension. List comprehensions are really useful and worth getting to know. In the code above the list comprehension will evaluate first. What is basically says is 'for each x
in Choice.objects.all()
put x.pk
in this list'. The queryset will then return every Question
for which there exists at least one related Choice
.
If what you want is a queryset of Choices
for each Question
then they are already available to you. For any instance of Question
, we'll call ours q
, you can get its associated Choices
with q.choice_set.all()
, which will return empty if there are none.
To implement: first change your DetailView
's name to avoid confusion with the generic one. Let's call it QuestionDetailView
. Add a context_object_name
to make your template more readable later. Don't tinker with the default queryset to exclude unpublished questions because the correct way to do this is with a model manager.
class QuestionDetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
context_object_name = 'question'
In your template for that view the question's related choices will already be available to you with something like {% for choice in question.choice_set.all %}
. That question
is called that because we gave it a context_object_name
so you could use any name you like. Note there's no need for ()
after the all
in a template.
If you need to do some other work with the choices before returning them to your template you can do that in the view. So, in your QuestionDetailView
you could add:
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
I'll explain what's happening here. This is adding extra context to what the view will return for your template to consume. The code I've written will just return all the question's choices so doesn't add to what was already there, but you can perform any other actions you care to. The modified choice set would then be available in your template as choices
so you could do {% for choice in choices %}
.
No matter what way you choose an empty choice set is possible and you can cater for it easily ({% if choices %}
or {% if question.choice_set.count %}
in the template, for example). You probably want to handle any empty queryset more elegantly than a 404 because you don't really want users being directed to error pages for a predictable result, such as an empty queryset.
这篇关于Django中查询查询器是空的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!