Search code examples
pythondjangodjango-1.7

Django 1.7 generic views


I'm currently going through Django's official tutorial, and I'm having trouble trying to understand how the generic views actually work.

Source code from the official documentation:

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


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

detail.html

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

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

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

results.html

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

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

Now, I understand that ListView and DetailView are default generic views provided by Django.

How do DetailView and ResultsView generate the question context variable in the detail.html and result.html? Also, how is the error_message context variable inside the detail.html generated by the DetailView ?


Solution

  • The question object is named after the model attribute of the generic view (in this case, Question). Detail views include such an object automatically.

    If you're asking how the specific question object is chosen, a detail view, by default, must be passed a pk value from the URL, which is then used to find that object. The relevant code from polls/urls.py is as follows:

    url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
    

    error_message, on the other hand, is not included in the generic views. It's only used in the example for the non-generic view, because that one includes it in the context explicitly:

    return render(request, 'polls/detail.html', {
        'question': p,
        'error_message': "You didn't select a choice.",
    })