防止发布没有选择的民意调查

Posted

技术标签:

【中文标题】防止发布没有选择的民意调查【英文标题】:Preventing polls without choices from being published 【发布时间】:2015-01-05 15:36:44 【问题描述】:

我一直在努力通过Django tutorial,我在第 5 部分,它要求我创建一个测试,看看是否正在发布没有选择的民意调查。对于我们所做的每一个其他测试,比如确保只发布过去(而不是未来)的民意调查,我们只需创建两个民意调查:一个在过去使用 pub_date,一个在未来:

def test_index_view_with_future_poll_and_past_poll(self):
        """
        Even if both past and future polls exist, only past polls should be
        displayed.
        """

        create_poll(question='past poll', days=-30)
        create_poll(question='future poll', days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_poll_list'],
            ['<Poll: past poll>'])

对于对应的视图,我们只是简单地添加了以下函数:

def get_queryset(self):
    """Return the last five published poll."""
    #Returns polls published at a date the same as now or before
    return Poll.objects.filter(pub_date__lte=timezone.now()).order_by('pub_date')[:5]

它只是使用 filter() 函数来过滤掉任何将来带有pub_date 的投票,这真的很简单。但我似乎无法在没有任何选择的情况下对民意调查做同样的事情,这就是我迄今为止对测试功能所做的:

class PollsAndChoices(TestCase):
    """ A poll without choices should not be displayed
    """
    def test_poll_without_choices(self):
        #first make an empty poll to use as a test
        empty_poll = create_poll(question='Empty poll', days=-1)
        poll = create_poll(question='Full poll',days=-1)
        full_poll = poll.choice_set.create(choice_text='Why yes it is!', votes=0)
        #create a response object to simulate someone using the site
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(response.context['latest_poll_list'], ['<Poll: Full poll>'])

这就是我对相关视图的看法:

class IndexView(generic.ListView):
    #We tell ListView to use our specific template instead of the default just like the rest
    template_name = 'polls/index.html'
    #We use this variable because the default variable for Django is poll_list
    context_object_name = 'latest_poll_list'

    def get_queryset(self):
        """Return the last five published poll."""
        #Returns polls published at a date the same as now or before
       return Poll.objects.filter(pub_date__lte=timezone.now()).order_by('pub_date')[:5]

    def show_polls_with_choices(self):
       """ Only publish polls that have choices """
       #Since choice_set displays a list we can use it to make sure a poll with an empty list
       #is not published
        for poll in Poll.objects.all():
            if poll.choice_set.all() is not []:
                return poll

基本上什么都没有发生,测试失败:

Traceback (most recent call last):
  File "C:\Users\ELITEBOOK\dropbox\programming\mysite\polls\tests.py", line 125, in    test_poll_without_choices
    self.assertQuerysetEqual(response.context['latest_poll_list'], ['<Poll: Full poll>'])
  File "C:\Users\Elitebook\Dropbox\Programming\virtualenvs\project\lib\site-  packages\django\test\testcases.py", line 829
, in assertQuerysetEqual
    return self.assertEqual(list(items), values)
AssertionError: Lists differ: ['<Poll: Empty poll>', '<Poll:... != ['<Poll: Full poll>']

First differing element 0:
<Poll: Empty poll>
<Poll: Full poll>

First list contains 1 additional elements.
First extra element 1:
<Poll: Full poll>

- ['<Poll: Empty poll>', '<Poll: Full poll>']
+ ['<Poll: Full poll>']

所以应用仍然在发布空民意调查和完整民意调查,有没有办法使用filter() 方法根据他们是否有选择来细化民意调查?

【问题讨论】:

***.com/a/844572/3033586 【参考方案1】:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'

def get_queryset(self):
    return Polls.objects.exclude(choice__isnull=True).filter(pub_date__lte=timezone.now()).order_by('-pub_date')[:10]

这可能是解决问题的最简单方法,因为它结合了两者;您的函数和视图工作所必需的 get_queryset

如果它用于 IndexView,您需要在您在 Index View 上运行的测试中创建至少一个选项

【讨论】:

你可以编辑你的答案而不是评论它来解释。【参考方案2】:
def show_polls_with_choices(self):    
    return Poll.objects.exlude(choice_set__isnull=True)


def get_queryset(self):
    """Return the last five published NOT EMPTY polls."""
    #Returns polls published at a date the same as now or before
    return self.show_polls_with_choices().filter(pub_date__lte=timezone.now()).order_by('pub_date')[:5]

【讨论】:

我仍然遇到同样的错误,正在发布民意调查。你发现我的测试代码有什么问题吗? 它说['&lt;Poll: Empty poll&gt;', '&lt;Poll:... != ['&lt;Poll: Full poll&gt;'] 所以一个列表!= 另一个列表,你从get_queryset 获得的第一个是['&lt;Poll: Empty poll&gt;', '&lt;Poll: Full poll&gt;'],第二个是你在测试中手动声明的['&lt;Poll: Full poll&gt;'] 所以如果你只想得到['&lt;Poll: Full poll&gt;'],你必须编辑你的get_queryset类似return self.show_polls_with_choices().filter(pub_date__lte=timezone.now()).order_by('pub_date')的东西 嘿,谢谢,那条线帮了很多忙。但另一个问题是其余的测试创建民意调查时没有为各自的测试选择。所以它也导致了这个测试失败。【参考方案3】:

我是这样做的:

def create_question(question_text, days):
    """
    Create a question with the given `question_text` and pulished the
    given number of `days` offset to now(negative for questions
    published in the past, positive for questions that have yet to be published).
    """
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)

def create_choice(question_text, days, choice_text=0):
    """
    Createing a question and choice with giver informations
    """
    question = create_question(question_text, days)
    if choice_text:
        question.choice_set.create(choice_text=choice_text, votes=0)
        return question
    else:
        return question

以上两个函数进行提问和选择。 这是测试部分


    def test_no_choice(self):
        """
        Will rise a 404 not found if the question hadnt any choice.
        """
        no_choice = create_choice(question_text="No Choice.", days=-2)
        url = reverse('polls:result', args=(no_choice.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_with_choice(self):
        """
        Will show the choice_text if thers was some.
        """
        question = create_choice(question_text='With Choice.', days=-2, 
        choice_text='With Choice')
        url = reverse('polls:result', args=(question.id,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

而且,你帮我完成了过滤部分 所以它是 50/50

【讨论】:

以上是关于防止发布没有选择的民意调查的主要内容,如果未能解决你的问题,请参考以下文章

如何对表示具有多个答案的民意调查的两个表使用一个查询?

有没有办法从 Instagram 故事中检索民意调查选民名单?

primefaces民意调查未更新

如果没有答案,如何防止提交表单的最后一个问题

Primefaces 一项民意调查“暂停”另一项民意调查

詹金斯民意调查错误的分支