• Aucun résultat trouvé

Basic Setup

Dans le document Projects Django (Page 144-148)

To get started with the comments application, you’ll only need to set up two templates, which will be used to preview a comment before posting it. But before you can preview a comment, you need to show a form for visitors to fill out. Let’s start with that.

Open up the entry detail template—coltrane/entry_detail.html—and go to the main content block, which looks like this:

{% block content %}

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

{{ object.body_html|safe }}

{% endblock %}

Go ahead and add a header that will distinguish the comment form:

{% block content %}

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

{{ object.body_html|safe }}

<h2>Post a comment</h2>

{% endblock %}

Now you just need to display the form. The comments system includes a custom template tag library which, among other things, can do just that. The tag library is called comments, so you’ll need to load it with the {% load %}tag:

{% block content %}

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

{{ object.body_html|safe }}

<h2>Post a comment</h2>

{% load comments %}

{% endblock %}

Now, the tag you want is called {% free_comment_form %}, and its syntax looks like this:

{% free_comment_form for app_name.model_name object_id %}

In other words, it wants an application name and model name to identify the model the comment will be attached to—these will be fed into the get_model()function you saw in Chapter 6—and the idof the specific object it’s going to be attached to, which will be available in the entry_detailtemplate as the variable {{ object.id }}. So you can fill in the tag like so:

{% block content %}

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

{{ object.body_html|safe }}

<h2>Post a comment</h2>

{% load comments %}

{% free_comment_form for coltrane.entry object.id %}

{% endblock %}

Note that you don’t put the braces around object.idhere. The braces, as in {{ object.id }}, are only used when you want to output the value of the variable. In a template tag, they’re not needed and, in fact, will cause an error. Template tags can resolve variables on their own (as you’ll see in Chapter 10 when you write a few tags that do that).

Now, go visit an entry, and you’ll see the comment form show up. But if you fill in a com-ment and hit the Preview button, you’ll see an ugly error telling you that the preview template doesn’t exist. Since this will vary from site to site, Django can’t provide it automatically. You will have to fill it in.

The template it wants is called comments/free_preview.html. So go to the project’s templatedirectory and create a new commentsdirectory inside it, then place the following into a template inside of that called free_preview.html:

{% extends "base.html" %}

{% block title %}| Post a comment{% endblock %}

{% block content %}

<h2>Post a comment</h2>

<p>Here's how your comment will look:</p>

<p>On {{ comment.submit_date|date:"F j, Y" }}, {{ comment.person_name }} said:</p>

{{ comment.comment }}

<input type="hidden" name="options" value="{{ options }}" />

<input type="hidden" name="target" value="{{ target }}" />

<input type="hidden" name="gonzo" value="{{ hash }}" />

</dd>

<dd><input type="submit" name="post" value="Post comment" /></dd>

</dl>

</form>

{% endblock %}

The view that handles this (which lives in django.contrib.comments.views, if you’d like to have a look at it) is concerned with doing two things: letting users preview their comments and validating the submitted comment to make sure that, for example, all the required fields are present. The validation routine makes use of Django’s form-handling system, which I’ll cover in detail a bit later on, but for now you can probably guess what’s going on in that part of the template. The remainder is simply showing a preview of the comment (each FreeComment object has fields named submit_date,person_name, and comment, representing the date the comment was posted, the name of the commenter, and the actual comment text).

It would be nice to have some safe way to let commenters use some basic HTML so that they can include things like links or text formatting in their comments. But Django’s template system will automatically escape the contents of the comment in order to prevent malicious HTML from being displayed.

To solve this, you need to have some way to allow some basic formatting—say, the Mark-down style of formatting you’re using for the entries and links in the blog—but forbid any raw HTML from being passed through. The Python Markdown module supports this through a

“safe mode” that will strip out raw HTML but process Markdown syntax normally, so that seems like an ideal way to solve it. The only question is how to apply it in the templates.

The answer is to use a template filter. Just as Django lets you define custom template tags, it will let you define custom filters as well. All you would need, then, is a filter that applies Markdown formatting, in safe mode, to a variable. The code for it would look like this:

from django import template from markdown import markdown def safe_markdown(value):

return markdown(value, safe_mode=True) register = template.Library()

register.filter(safe_markdown)

Note that this is much simpler than defining a custom tag. A filter is simply a function that gets passed a value and is expected to return another value, which will become part of the template's rendered output. Registering a filter uses register.filter(), as opposed to the register.tag()for custom template tags.

But you don’t actually need to write this filter because a set of text-to-HTML formatting filters is bundled with Django in the django.contrib.markupapplication. This application doesn’t provide any models, but it does include a library of custom template filters that know how to apply common text-to-HTML formatting systems like Markdown.

To use it, you’ll need to do two things. First, add django.contrib.markupto the INSTALLED_

APPSsetting of your project. (There’s no need to run manage.py syncdb, since this application doesn’t provide any models to be installed in the database.) Next, load its library of custom filters, which is named markup. Here’s how it will look in the template:

{% load markup %}

<h2>Post a comment</h2>

<p>Here's how your comment will look:</p>

<p>On {{ comment.submit_date|date:"F j, Y" }}, {{ comment.person_name }} said:</p>

{{ comment.comment|markdown:"safe" }}

This will apply Markdown formatting, using the safe mode that strips raw HTML, to the comment, which is precisely what you want.

One more template is required to complete the process. After a comment is successfully posted, the comment-submission view will issue an HTTP redirect to a second view, which uses the template comments/posted.html. This template will receive one variable, object, which is the content object the comment was attached to and which can be used to show a link back to that object. For example, you might place something like this in your

comments/posted.htmltemplate:

<p>Your comment was posted successfully; you can see it by

<a href="{{ object.get_absolute_url }}">returning to the discussion</a>.</p>

Dans le document Projects Django (Page 144-148)