object不可迭代和/或NoReverseMatch

时间:2013-12-20 18:29:34

标签: django django-views

晚上好。我是Django的新手,我正在玩民意调查教程。我添加了一个新模型" Section"它充当一组问题的父母。这样做很好,因为它显示了html页面上一节的所有问题。

我现在尝试做的是每页只显示一个问题,将答案保存到数据库并从该部分获得下一个问题。我尝试了几种不同的方法,但没有任何作用。我希望你们能引导我走向正确的方向。

URLS.PY
urlpatterns = patterns('',
    url(
        regex=r'^$', 
        view=UmfrageView.as_view(), 
        name='umfrage'
    ),
    url(
        regex=r'^(?P<slug>[-\w]+)/$',
        view=DetailView.as_view(),
        name='detail'
    ),
    url(
        regex=r'^(?P<question_id>\d+)/$',
        view=vote,
        name='vote'
    ),
 )

尝试从一个部分获得第一个问题:

VIEWS.PY
class DetailView(ListView):
    model = Question
    context_object_name = 'latest_question_list'
    template_name = 'itbarometer/detail.html'

    def get_queryset(self, **kwargs):
        # Get question set via section slug
        slug = self.kwargs.get('slug') or kwargs.get('slug')
        qs = Question.objects.filter(section__slug=slug).order_by('pub_date')
        try:
            return qs[0]
        except IndexError:
            return None

def vote(request, question_id):
    p = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = p.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form
        return render(request, 'itbarometer/umfrage.html', {
            'question': p,
            'error_message': "Bitte eine Antwort auswählen.",})
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:umfrage'))

HTML模板detail.html:

{% if latest_question_list %}
    {% for question in latest_question_list %}
        <form action="{% url 'polls:vote' question.id %}" method="post">
            <fieldset>
                <legend>{{ question.question_text }}</legend>
                {% csrf_token %}
                {% for choice in question.choice_set.all %}
                    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
                    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
                {% endfor %}
            </fieldset>
            <input class="button small" type="submit" value="Save" />
        </form>
    {% endfor %}
{% endif %}

但我会得到

例外值:
&#39;问题&#39;对象不可迭代

在latest_question_list&#34;中删除&#34;的问题时在detail.html我会得到

异常类型:NoReverseMatch 例外价值: 反对&#39;投票&#39;有参数&#39;(&#39;&#39;,)&#39;和关键字参数&#39; {}&#39;未找到。尝试过1种模式:[u&#39; umfragen /(?P \ d +)/ $&#39;]

如果我进一步删除&#34; {%url&#39;民意调查:投票&#39; question.id%}&#34;从表单操作,我将获得一个空的表单布局。我怀疑没有数据传输。

可能是什么问题?

编辑:models.py

class Section(models.Model):
    section_text = models.CharField(max_length=255)
    section_description = models.TextField(blank=False)
    slug = models.SlugField(unique=True, null=True)

    def __unicode__(self):
        return self.section_text

    def save(self, *args, **kwargs):
        self.slug = slugify(self.section_text)
        super(Section, self).save(*args, **kwargs)


class Question(models.Model):
    section = models.ForeignKey(Section)
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __unicode__(self):
        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)

2 个答案:

答案 0 :(得分:0)

  

异常值:'问题'对象不可迭代

您收到此消息是因为get_queryset中的DetailView正在返回问题对象而不是查询集。如果您将return qs[0]更改为return qs,则会返回一个查询集,而不是该列表中的第一个问题。

  

异常类型:NoReverseMatch异常值:反向“投票”,参数'('',)'和关键字参数'{}'未找到。尝试过1种模式:[u'umfragen /(?P \ d +)/ $']

现在已删除循环,未定义question。对url标记的调用失败,因为它现在缺少一个参数。

布局为空,因为它引用了question中的值,但question从未设置过,因为它是在循环中设置的。

如果您确实只想处理1个问题,请删除循环并将context_object_name = 'latest_question_list'更改为question,因为这是您的模板引用的内容,或者考虑将DetailView子类化为{{3}}而不是{ {1}}并实施ListView而不是get_object()

答案 1 :(得分:0)

您正在使用ListView(即使您将其称为DetailView :)),它是为了显示对象列表而构建的。

第一步是实际使用Django附带的the generic DetailView,它是为了显示单个对象而构建的。像这样:

from django.views.generic import DetailView

class YourView(DetailView):
    model = Question

这会自动将与网址中的slug匹配的Question分配给模板变量question。从模板中删除{% for .. %}{% endfor %}以及{% if ... %} / {% endif %}对,并显示单个问题。