• Aucun résultat trouvé

Entry Detail

Dans le document Projects Django (Page 127-130)

The generic view that shows a single entry uses the template coltrane/entry_detail.htmland provides one variable, object, which will be the entry. The first part of this template is easy:

{% extends "base_entries.html" %}

{% block title %}{{ block.super }} | {{ object.title }}{% endblock %}

{% block content %}

<h2>{{ object.title }}</h2>

{{ object.body_html|safe }}

{% endblock %}

The sidebar is a bit trickier. You can start out by showing the entry’s pub_date:

{% block whatis %}

<p>This is an entry posted to my blog on {{ object.pub_date|date:"F j, Y" }}.</p>

Now, it would be nice to show the categories by saying something like, “This entry is part of the categories ‘Django’ and ‘Python.’” But there are several things to take into account here:

• For an entry with one category you want to say “part of the category.” But for an entry with more than one, it needs to be “part of the categories,” and for an entry with no cat-egories, you need to say, “This entry isn’t part of any categories.”

• For an entry with more than two categories, you’ll need commas between category names and the word “and” before the final category. But for an entry with two cate-gories, you don’t need the commas, and for an entry with only one category, you don’t need commas or the “and.”

If there aren’t any categories for an entry, {{ object.categories.count }}will be 0, which is Falseinside an {% if %}tag, so you can start with a test for that:

{% if object.categories.count %}

. . .you'll fill this in momentarily. . . {% else %}

<p>This entry isn't part of any categories.</p>

{% endif %}

Now you need to handle the difference between “category” and “categories.” Since this is a common problem, Django includes a filter, called pluralize, which can take care of it. The pluralizefilter, by default, outputs nothing if applied to a variable that evaluates to the num-ber 1, but outputs an “s” otherwise. It also accepts an argument that lets you specify other text to output. In this case, you want a “y” for the singular case and “ies” for the plural, so you can write:

{% if object.categories.count %}

<p>This entry is part of the

category{{ object.categories.count|pluralize:"y,ies" }}

You’ll get “category” when there’s only one category and “categories” otherwise.

Finally, you need to loop over the categories. One option would be to join the list of cate-gories using commas. In Python code, you’d write:

', '.join(object.categories.all())

And Django’s template system provides a joinfilter, which works the same way:

{{ object.categories.all|join:", " }}

But you want to have the word “and” inserted before the final category in the list, and join can’t do that. The solution is to use the {% for %}tag and to take advantage of some useful variables it makes available. Within the {% for %}loop, the following variables will automati-cally be available:

• forloop.counter: The current iteration of the loop, counting from 1. The fourth time through the loop, for example, this will be the number 4.

• forloop.counter0: Same as forloop.counter, but starts counting at 0 instead of 1. The fourth time through the loop, for example, this will be the number 3.

• forloop.revcounter: The number of iterations left until the end of the loop, counting down to 1. When there are four iterations left to go, for example, this will be the number 4.

• forloop.revcounter0: Same as forloop.revcounter, but counts down to 0 instead of 1.

• forloop.first: A boolean value—it will be Truethe first time through the loop and Falsethe rest of the time.

• forloop.last: Another boolean—this one is Truethe last time through the loop and Falsethe rest of the time.

Using these variables, you can work out the proper presentation. Expressed in English, the logic works like this:

1. Display a link to the category.

2. If this is the last time through the loop, don’t display anything else.

3. If this is the next-to-last time through the loop, display the word “and.”

4. Otherwise, display a comma.

And here it is in template code:

{% for category in object.categories.all %}

<a href="{{ category.get_absolute_url }}">{{ category.title }}</a>

{% if forloop.last %}{% else %}

{% ifequal forloop.revcounter0 1 %}and {% else %}, {% endifequal %}

{% endif %}

s {% endfor %}

There are really two important bits here:

• {% if forloop.last %}{% else %}: This does absolutely nothing if you’re in the last trip through the loop.

• {% ifequal forloop.revcounter0 1 %}: This determines whether you’re in the next-to-last trip through the loop in order to print the “and” before the final category.

Here’s the full sidebar block so far:

{% block whatis %}

<p>This is an entry posted to my blog on {{ object.pub_date|date:"F j, Y" }}.</p>

{% if object.categories.count %}

<p>This entry is part of the

category{{ object.categories.count|pluralize:"y,ies" }}

{% for category in object.categories.all %}

<a href="{{ category.get_absolute_url }}">{{ category.title }}</a>

{% if forloop.last %}{% else %}

{% ifequal forloop.revcounter0 1 %}and {% else %}, {% endifequal %}

{% endif %}

{% endfor %}

</p>

{% else %}

<p>This entry isn't part of any categories.</p>

{% endif %}

{% endblock %}

Handling tags will work much the same way. {{ object.tags }}will return the tags for the Entry, and a similar bit of template code can handle them. And with that, you have a pretty good entry detail template:

{% extends "base_entries.html" %}

{% block title %}{{ block.super }} | {{ object.title }}{% endblock %}

{% block content %}

<h2>{{ object.title }}</h2>

{{ object.body_html }}

{% endblock %}

{% block whatis %}

<p>This is an entry posted to my blog on {{ object.pub_date|date:"F j, Y" }}.</p>

{% if object.categories.count %}

<p>This entry is part of the

category{{ object.categories.count|pluralize:"y,ies" }}

{% for category in object.categories.all %}

<a href="{{ category.get_absolute_url }}">{{ category.title }}</a>

{% if forloop.last %}{% else %}

{% ifequal forloop.revcounter0 1 %}and {% else %}, {% endifequal %}

{% endif %}

{% endfor %}

</p>

{% else %}

<p>This entry isn't part of any categories.</p>

{% endif %}

{% endblock %}

Dans le document Projects Django (Page 127-130)