防止发布没有选择的民意调查
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]
【讨论】:
我仍然遇到同样的错误,正在发布民意调查。你发现我的测试代码有什么问题吗? 它说['<Poll: Empty poll>', '<Poll:... != ['<Poll: Full poll>']
所以一个列表!= 另一个列表,你从get_queryset
获得的第一个是['<Poll: Empty poll>', '<Poll: Full poll>']
,第二个是你在测试中手动声明的['<Poll: Full poll>']
所以如果你只想得到['<Poll: Full poll>']
,你必须编辑你的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
【讨论】:
以上是关于防止发布没有选择的民意调查的主要内容,如果未能解决你的问题,请参考以下文章