Manas Chaturvedi
Manas Chaturvedi

Reputation: 5540

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 ?

Upvotes: 0

Views: 158

Answers (2)

Paulo Almeida
Paulo Almeida

Reputation: 8061

DetailView has a context_object_name parameter, which you can use to set the name of the object in the template, but if you don't set it, the get_context_object_name method does this:

def get_context_object_name(self, obj):
    """
    Get the name to use for the object.
    """
    if self.context_object_name:
        return self.context_object_name
    elif isinstance(obj, models.Model):
        return obj._meta.model_name
    else:
        return None

It uses the name of the model. Then get_context_data of the SingleObjectMixin puts that identifier in the context. In any case, you can also access the object with the object identifier.

I'm sure you can read all of this in the Django documentation, but there is a nice page where you can explore class based views

Upvotes: 1

Daniel Robinson
Daniel Robinson

Reputation: 3387

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.",
})

Upvotes: 2

Related Questions