Содержание
Данная глава временно взята из первой версии книги и подлежит корректировке. Вы можете помочь с этим!
Перевод © Попов Руслан <radz • yandex • ru>
Одним из множества преимуществ использования Python является философия «всё включено»: когда вы устанавливаете Python, он поставляется с большой стандартной библиотекой пакетов, которые вы можете начать использовать немедленно, без необходимости скачивать что-нибудь ещё. Django старается следовать этой философии и включает в себя все свои стандартные библиотеки модулей, полезных для задач веб разработки. Эта глава рассказывает об этих модулях.
Стандартная Django находится в пакете django.contrib. В каждом субпакете находится отдельная часть дополнительного функционала. Эти части не всегда зависят друг от друга, но некоторые могут.
Нет жёсткого требования для типов функциональности в django.contrib. Некоторые из пакетов включают в себя модели (и следовательно требуют, чтобы вы установили их таблицы в базу данных), но другие могут состоять полностью из кода или шаблонов.
Единственная общая особенность пакетов django.contrib — если вы полностью удалите пакет django.contrib, вы сможете использовать основные компоненты Django без проблем. Когда разработчики добавляют новую функциональность в Django они используют это правило при рассмотрении вопроса о том, должна ли эта функциональность быть размещена в django.contrib или где-то в другом месте.
Библиотека django.contrib содержит следующие пакеты:
admin: Автоматический сайт администратора. Обратитесь к главам «Интерфейс администратора Django» и глава «Интернационализация».
auth: Среда аутентификации и авторизации. Обратитесь к главе «Сессии, пользователи и регистрация».
comments: Среда управления комментариями. Обратитесь к разделу «Среда управления комментариями» данной главы.
contenttypes: Среда подключения к «типам» данных, в которой каждая установленная модель Django является отдельным типом данных. Эта среда используется другими модулями библиотеки и в основном ориентировано на очень продвинутых Django разработчиков. Эти разработчики должны получить больше информации по этому модулю, читая исходный код в django/contrib/contenttypes/.
csrf: Защита против Cross-Site Request Forgery (CSRF). Смотрите далее секцию «Защита от CSRF».
flatpages: Среда для управления простым «плоским» HTML представлением в базе данных. Смотрите далее секцию «Статические страницы».
humanize: Набор шаблонных фильтров, полезных для «очеловечивания» данных. Смотрите далее секцию «Очеловечивание данных».
markup: Набор шаблонных фильтров, которые реализуют ряд стандартных языков разметки. Смотрите далее секцию «Фильтры разметки».
redirects: Среда управления перенаправлениями. Смотрите далее секцию «Перенаправления».
sessions: Среда управления сессиями. Смотрите главу «Сессии, пользователи и регистрация».
sitemaps: Среда генерации XML файлов для карты сайта. Смотрите главу «Генерация данных, отличных от HTML».
sites: Среда управления множеством сайтов на основе единой базы данных и Django. Обратитесь к следующей секции «Сайты».
syndication: Среда управления средствами трансляции в форматах RSS и Atom. Обратитесь к секции «Средства трансляции».
Остальная часть этой главы посвящена деталям каждого модуля пакета django.contrib, которые мы ещё не рассматривали в нашей книге.
Перевод статьи http://code.djangoproject.com/wiki/UsingFreeComment.
Django поставляется с простой системой комментариев, которая может сэкономить вам кучу времени в случае, если вам потребуется обеспечить возможность для пользователей комментировать, например, заметку вашего блога или фотографию.
Система комментариев является приложением
Django. Следовательно, требуется прописать его в параметре
INSTALLED_APPS
файла конфигурации
проекта:
INSTALLED_APPS = (
[...]
'django.contrib.comments',
)
Если вы используете свои представления и точно не
используете базовые представления, вам потребуется добавить
нижеприведённую строчку в начала соответствующего файла
urls.py
. Базовые представления сами
подключают этот класс, при их использовании об этом можно не
беспокоиться.
from django.contrib.comments.models import FreeComment
Добавьте следующий шаблон URL в глобальный файл привязки:
urlpatterns = patterns('',
[...]
(r'^comments/', include('django.contrib.comments.urls')),
}
Потребуется обновить вашу базу данных, чтобы там появилась необходимая таблица. Для этого следует остановить веб сервер и выполнить python manage.py syncdb.
В каждом шаблонном файле, который должен будет предоставлять доступ к комментариям, следует подгрузить соответствующий пакет (вставьте эту строку в самое начало шаблона):
{% load comments %}
Для получения доступа к комментариям объекта вам нужен только идентификатор этого объекта. При его наличии вы можете получить сами комментарии, информацию об их количестве и другую информацию.
В шаблоне object_list вы можете делать
следующее для того, чтобы добавить информацию о количестве
комментариев для каждой записи блога в
списке. Нижеприведённый пример предполагает, что вы
работаете над приложением blog с классом
entry
, у которого есть поля
title и summary, а также
метод get_absolute_url()
, который
возвращает абсолютный URL для страницы с записью блога.
Замечание
Следует отметить, что имя класса должно всегда быть
указано в нижнем регистре. Например, если класс имеет
имя Entry
, все обращения к нему
будут идти как к blog.entry.
<ul>
{% for object in object_list %}
{% get_free_comment_count for blog.entry object.id as comment_count %}
<li>
<h2><a href="{{ object.url }}">{{ object.title }}</a></h2>
<p class="description">{{ object.summary}}</p>
<p class="details">
<a href="{{ object.get_absolute_url }}">
{{ comment_count }} Comments
</a>
</p>
</li>
{% endfor %}
</ul>
Базовое представление archive_index работает почти так как описанное в предыдущей секции, только итерация происходит по объектам из коллекции latest, а не по object_list:
<ul>
{% for object in latest %}
{% get_free_comment_count for blog.entry object.id as comment_count %}
[...]
{% endfor %}
</ul>
В архивах, отсортированных по дате (таких как archive_year или archive_month), коллекция, по которой производится итерация называется «object_list». archive_index является только базовым представлением с latest.
Обычно добавление комментариев разрешено пользователям на страницах с детальной информацией об объекте. Можно разрешить добавление комментариев откуда угодно, но для простоты данный пример не будет так делать. При использовании любых базовых представлений для отображения детальной информации, таких как django.views.generic.list_detail.object_detail или django.views.generic.date_based.object_detail, у вас будет идентификатор объекта в object.id, таким образом получение информации о количестве комментариев для этого объект будет несложным:
{% get_free_comment_count for blog.entry object.id as comment_count %}
Для того, чтобы получить список комментариев, необходимо
использовать нижеприведённый пример, который помещает список
комментариев в шаблонную переменную
comment_list
:
{% get_free_comment_list for blog.entry object.id as comment_list %}
Каждый объект object
в
comment_list
имеет следующие поля:
comment.person_name: Имя комментатора.
comment.submit_date: Дата и время отправки комментария. Вы можете пропустить эту информацию через фильтр date для форматирования строки с датой. Это будет показано в примере далее.
comment.comment: Текст комментария. Не забывайте экранировать его с помощью фильтра escape для предотвращения инъекций вредоносного кода. Это будет показано в примере далее.
comment.is_public: Разрешение на публикацию комментария (TODO: надо понять как мы даём это разрешение).
comment.ip_address: IP адрес комментатора.
comment.approved: Разрешение на публикацию от представителя сайта (TODO: узнать как оно реализовано).
А также следующие встроенные методы:
comment.get_absolute_url: Метод возвращает абсолютный URL для текущего комментария. Например, если комментарий был написан для записи блога размещённой по ссылке /blog/some-slug/, то будет возвращён URL /blog/some-slug/#c4, где 4 — это идентификатор комментария.
comment.get_content_object: Метод возвращает объект для которого было создан текущий комментарий.
Система комментирования не позволяет вам добавлять другие типы данных, такие как адрес электронной почты комментатора. Это может быть исправлено в будущем.
Пример:
{% get_free_comment_count for blog.entry object.id as comment_count %}
<h2><a href="{{ object.url }}">{{ object.title }}</a></h2>
<em>{{ object.description }}</em>
<div class="article_menu">
<b>Added on {{ object.add_date|date:"F j, Y" }}</b>
<a href="{{ object.get_absolute_url }}#comments">{{ comment_count }}
Comment{{ comment_count|pluralize }}</a>
</div>
{% get_free_comment_list for blog.entry object.id as comment_list %}
<h2 id="comments">Comments</h2>
{% for comment in comment_list %}
<div class="comment_{% cycle odd,even %}" id="c{{ comment.id }}">
<span class="comnum">
<a id="c{{ comment.id }}" href="#c{{ comment.id }}">
#{{ forloop.counter }}
</a>
</span>
<p>
<b>{{ comment.person_name|escape }}</b> commented,
on {{ comment.submit_date|date:"F j, Y" }}
at {{ comment.submit_date|date:"P" }}:
</p>
{{ comment.comment|escape|urlizetrunc:40|linebreaks }}
</div>
{% endfor %}
<h2>Post a comment</h2>
{% free_comment_form for blog.entry object.id %}
Django поставляется со встроенными стандартными шаблонами для системы комментирования.
Вы можете переопределить любой из них, создав каталог
comments
в каталоге с вашими шаблонами
и соответствующие шаблоны в нём.
Этот шаблон (freeform.html
) содержит
код формы, с помощью которой пользователь отправляет
комментарий. В вышеприведённом примере, он подключался
так:
<h2>Post a comment</h2>
{% free_comment_form for blog.entry object.id %}
Пример шаблона:
{% if display_form %}
<form action="/comments/postfree/" method="post">
<p>Your name: <input type="text" id="id_person_name" name="person_name" /></p>
<p>Comment:<br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="Preview comment" /></p>
</form>
{% endif %}
Если вы не желаете использовать страницу для предварительного просмотра комментария, просто замените name="preview" на name="post".
Этот шаблон
(free_preview.html
)используется при
просмотре пользователем своего комментария перед его
отправкой.
Пример:
<h1>Preview your comment</h1>
<form action="/comments/postfree/" method="post">
{% if comment_form.has_errors %}
<p><strong style="color: red;">Please correct the following errors.</strong></p>
{% else %}
<div class="comment">
{{ comment.comment|escape|urlizetrunc:"40"|linebreaks }}
<p class="date small">Posted by <strong>{{ comment.person_name|escape }}</strong></p>
</div>
<p><input type="submit" name="post" value="Post public comment" /></p>
<h1>Or edit it again</h1>
{% endif %}
{% if comment_form.person_name.errors %}
{{ comment_form.person_name.html_error_list }}
{% endif %}
<p><label for="id_person_name">Your name:</label> {{ comment_form.person_name }}</p>
{% if comment_form.comment.errors %}
{{ comment_form.comment.html_error_list }}
{% endif %}
<p>
<label for="id_comment">Comment:</label>
<br />
{{ comment_form.comment }}
</p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p>
<input type="submit" name="preview" value="Preview revised comment" />
</p>
</form>
Этот шаблон (posted.html
)
отображается после того как пользователь отправит
комментарий. Вы можете получить доступ к
прокомментированному объекту через контекстную переменную
object
.
Пример:
<h1>Comment posted successfully</h1>
<p>Thanks for contributing.</p>
{% if object %}
<ul>
<li><a href="{{ object.get_absolute_url }}">View your comment</a></li>
</ul>
{% endif %}
В настоящее время
django.contrib.comments.views.comments в
методе post_free_comment()
имеет жёстко
определённый адрес перенаправления на
posted.html. Если вы желаете, чтобы отправка
комментария возвращала пользователя на комментируемую
страницу, вы можете переопределить метод
post_free_comment()
и добавить
перенаправление в другое место после отправки
комментария. URL может передаваться в виде скрытого
параметра в шаблоне freeform.html
. Для
этого потребуется создать обработчик в
views.py
:
from django.contrib.comments.views.comments import post_free_comment
from django.http import HttpResponseRedirect
def my_post_free_comment(request):
if request.has_key('url') and not request.has_key('preview'):
response = post_free_comment(request)
# Check there's a url to redirect to, and that post_free_comment worked
if len(request['url'].strip()) > 0 and
isinstance(response, HttpResponseRedirect):
return HttpResponseRedirect(request['url'])
# Fall back on the default post_free_comment response
return response
return post_free_comment(request)
После этого потребуется перенаправить запросу на это представление вместо оригинального. Для этого, перед строкой:
(r'^comments/', include('django.contrib.comments.urls.comments')),
надо добавить строку:
(r'^comments/postfree/', 'views.my_post_free_comment'),
Теперь надо добавить в форму скрытое поле с URL. Но как
получить текущий URL в шаблонной переменной? Для этого
потребуется активировать шаблонный контекстный процессор
request добавив следующий код в файл
settings.py
:
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)
После активации контекстного процессора шаблонам будет
доступна переменная request
. Используя
эту переменную вы можете выполнить
request.get_full_path для получения текущего
URL. Внесём эти изменения в
freeform.html
:
{% load i18n %}
{% if display_form %}
<form action="/comments/postfree/" method="post">
<p>
<label for="id_person_name">{% trans "Your name:" %}</label>
<input type="text" id="id_person_name" name="person_name" />
</p>
<p>
<label for="id_comment">{% trans "Comment:" %}</label><br />
<textarea name="comment" id="id_comment" rows="10" cols="60"></textarea>
</p>
<p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<input type="hidden" name="url" value="{{ request.get_full_path }}" />
<input type="submit" name="preview" value="{% trans "Preview comment" %}" />
</p>
</form>
{% endif %}
В free_preview.html
добавим:
<input type="hidden" name="url" value="{{ request.url }}" />
перед
<p><input type="submit" name="preview" value="Preview revised comment" /></p>
Этого должно быть достаточно!
Список свежих комментариев. Нижеприведённый код отображает в виде списка последние комментарии для всего вашего сайта, не обращая внимания на приложения:
<h1>Recent comments</h1>
<p>
{% if has_previous %}
<a href="?page={{ previous }}">Previous</a> |
{% endif %}
Page {{ page }} of {{ pages }}
{% if has_next %}
| <a href="?page={{ next }}">Next</a>
{% endif %}
</p>
{% for comment in object_list %}
<div class="comment" id="c{{ comment.id }}">
<h3>
<a href="{{ comment.get_absolute_url }}">
{{ comment.person_name|escape }}
<span class="small quiet">
{{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}
</span>
</a>
</h3>
{{ comment.comment|escape|urlizetrunc:"40"|linebreaks }}
</div>
{% endfor %}
<p>
{% if has_previous %}
<a href="?page={{ previous }}">Previous</a> |
{% endif %}
Page {{ page }} of {{ pages }}
{% if has_next %}
| <a href="?page={{ next }}">Next</a>
{% endif %}
</p>
3 comments | Make a comment
test
answer to max.kashuba
test
test
answer to max.kashuba
test
test