2014-09-26 78 views
1

說我有過一段代碼:檢查查詢集是在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' object has no attribute 'filter'

這是從Django tutorial的最底部它提到

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.

我要去哪裏錯了多久?

編輯:

我改變了代碼引用 「all_entries」 有:

all_entries = Choice.objects.all().count() 

if all_entries > 0: 
    return Question.objects.filter(pub_date__lte=timezone.now()) 

但只是返回所有的問題,他們是否有選擇或不...

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對於cms_mgr

基本上我想檢查與指定問題相關聯的選擇是空號。當我去這個鏈接 - http://127.0.0.1:8000/polls/3/我想從id('3')得到問題並檢查它包含的選項的數量。

+0

什麼是'問題'模型代碼的樣子? – 2014-09-26 12:08:36

+0

請參閱編輯 – Jon 2014-09-26 12:12:53

回答

4

只有當他們有相關選擇時才能獲得所有問題的一種方法是獲取Choices列表而不是問題,然後評估您的查詢。例如:

Question.objects.filter(pk__in=[x.question.pk for x in Choice.objects.all()]) 

方括號內的位是list comprehension。列表理解是非常有用的,值得了解。在上面的代碼中,列表理解將首先評估。基本上說的是'對於每個xChoice.objects.all()x.pk放在這個列表中'。查詢集將返回每Question,其中至少存在一個相關的Choice

如果你想要的是每個QuestionChoices的查詢集,那麼它們已經可用。對於Question的任何實例,我們將其稱爲我們的q,您可以獲得其關聯的Choicesq.choice_set.all(),如果沒有,它將返回空。

執行:首先更改DetailView的名稱以避免與通用名稱混淆。我們稱之爲QuestionDetailView。添加一個context_object_name以使您的模板更具可讀性。不要修改默認查詢集以排除未發佈的問題,因爲正確的方法是使用model manager

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 %}

無論您選擇哪種方式,您都可以選擇一個空白選項,並且您可以輕鬆應對(例如,模板中的{% if choices %}{% if question.choice_set.count %})。您可能想要比404更優雅地處理任何空的查詢集,因爲您不希望用戶被定向到可預測結果的錯誤頁面,如空的查詢集。

+0

'x'是什麼?這看起來與你的想法相似嗎? Question.objects.filter(pk__in = [Choice.objects.all()中的x的Question.id)) – Jon 2014-09-26 13:31:35

+0

謝謝,現在至少編譯好了,但返回的選擇數量似乎只有2個。我有3個問題 - 一個包含3個選擇,一個包含2個選擇,另一個包含空白。我期待總共有5個選擇。另外,有沒有一種方法可以從這個列表中獲得問題ID的選擇? – Jon 2014-09-26 13:44:27

+0

它呢?您的代碼似乎可以從所有問題中獲得全部選擇。獲得2的價值讓我感到困惑,因爲一方面總共有5個選擇,另一方面,我需要爲這個特定問題得到多少選擇。 – Jon 2014-09-26 14:02:38

1

如果all_entries爲而不是爲空,則不會返回任何內容。如果一個函數沒有顯式地返回一個值,Python會返回None

+0

謝謝,它阻止了錯誤,但現在它顯示了問題,無論選擇的數量如何。 – Jon 2014-09-26 12:15:15

0

你想要做的並不像看起來那麼容易。您必須根據選擇的數量篩選問題查詢集,而不是檢查選擇是否存在,然後返回問題。

您應該查看this other answer以瞭解如何使用註釋完成此操作。

+0

是不是有一個更簡單的方法?我已經有了Question對象,難道你不知道如何從對象中獲取選項嗎? – Jon 2014-09-26 12:53:01

+0

這是當你使用'choice_set'時。對於任何'問題''q',其相關的'選擇'是'q.choice_set.all()'。 – 2014-09-26 14:27:12

0

也許值得一提的是本系列後面有一個教程part 7,它提供了從根處理以下問題的正確方法的提示。

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.

我想解決它是爲了避免產生「問題沒得選擇」擺在首位的最佳方法(假設沒有人會直接與數據庫發脾氣)。 本教程將教您如何修改管理網站頁面,我們應該只允許管理員添加至少2個選項的問題。