Django中查询查询器是空的 [英] Check queryset is empty in Django

查看:141
本文介绍了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( )])

方括号内的位是一个。* python.org / 2 / tutorial / datastructures.html#list-comprehensionsrel =nofollow列表的理解真的很有用,值得了解。在上面的代码中,列表理解将首先进行评估。基本上说,对于中的每个 x ,Choice.objects.all() put x.pk 在这个列表'。然后,查询器将返回每个问题,其中存在至少一个相关的选项



如果你想要的是每个问题选项的查询,那么他们已经可供你使用对于问题的任何实例,我们将称为我们的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆