如何将对象的id转换为Django中的GenericView?

时间:2016-05-24 17:46:06

标签: python django

目前,我正处于Django的末尾,并希望添加一项功能来检查所使用的Question对象是否确实有任何选择。现在,它不会显示任何盒子并给我一个“投票”按钮,这实际上是无用的,因为我无法检查任何盒子。

我尝试使用'pk'关键字,当我进入网页时应该将其传递给DetailView,如下所示:

url(r'^specifics/(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),

但是当我尝试在我的DetailView中使用pk变量时,它会抱怨它不知道pk名称下的任何关键字。我特别得到这个错误:NameError: name 'pk' is not defined。在我的details.html中,我尝试打印出{{ question.pk }},这样做完美无缺(但我怀疑这是由于views.py中的投票功能)。

以下是我的网络应用中的DetailView和vote():

class DetailView(generic.DetailView):
    question = get_object_or_404(Question, pk=pk)
    model = Question
    template_name = 'polls/detail.html'
    question_exist = Question.objects.exists()
    empty_choice = question[pk].choice_query.exists()

    def get_queryset(self):
        """ Exclude any unpublished questions. """
        return Question.objects.filter(pub_date__lte=timezone.now())

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except(KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice!",
            })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return HttpResonseRedirect after POST success, prevents
        # data from being posted twice if someone hits the back button!
        return HttpResponseRedirect( reverse('polls:results', args=(question.id, )) )

这是我的detail.html:

<h1> {{ question.question_text }} </h1>

{% if error_message %}<p> <strong> {{ error_message }} </strong> </p> {% endif %}
{% if empty_choice %}
        <p> There are no choices!  </p>
{% else %}
        <form action="{% url 'polls:vote' question.id %}" method="post">
                {% 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 %}
                <input type="submit" value="Vote" />
        </form>
{% endif %}
{{ question.pk }}

question.pk在每个网站中返回正确的数字,但是当我尝试在DetailView中使用它时,Django说它不明白pk是什么。为什么呢?

2 个答案:

答案 0 :(得分:2)

问题是您在定义班级时尝试访问pk

class DetailView(generic.DetailView):
    question = get_object_or_404(Question, pk=pk)

由于您无法访问pk,因此无法正常工作。处理请求时,您可以访问类方法中的pk

class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)
        context['empty_choice'] = self.object.choice_query.exists()
        return context

    def get_queryset(self):
        """ Exclude any unpublished questions. """
        return Question.objects.filter(pub_date__lte=timezone.now())

请注意,您不必使用get_object_or_404来解决问题 - 通用视图的get_object方法会为您解决此问题。

将您的观点命名为其他内容可能会更好(例如QuestionDetailView,这样就不会与Django DetailView混淆。

答案 1 :(得分:1)

在类构造期间不能使用pk,在请求进入之前不会使用pk。在可以采取任何请求之前将django加载到内存中时构造类。基本上你不能使用以下几行,因为当他们执行时,django对class DetailView(generic.DetailView): question = get_object_or_404(Question, pk=pk) question_exist = Question.objects.exists() empty_choice = question[pk].choice_query.exists() 没有任何线索:

get_queryset

相反,您应使用pk函数,该函数仅在请求进入时调用。self.kwargs将在class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' def get_queryset(self): """ Exclude any unpublished questions. """ return get_object_or_404( Question, pk=self.kwargs['pk'], pub_date__lte=timezone.now() ) 中(因为您确实在其中为其命名) URLconf正则表达式:

^delete\(.*\)$

    ^ assert position at start of the string
    delete matches the characters delete literally (case sensitive)
    \( matches the character ( literally
    .* matches any character (except newline)
        Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
    \) matches the character ) literally
    $ assert position at end of the string

(这个例子可能有一些怪癖,我还没有对它进行测试。为此道歉。我回家后会对它进行测试)