Аутентифицированный комментарий в Django 1.1?

(Теперь, когда Django 1.1 находится в статусе кандидата на выпуск, самое время задать этот вопрос.)

Я везде искал способы расширить приложение комментариев Django для поддержки аутентифицированных комментариев. Прочитав модель комментариев несколько раз, я обнаружил, что от ForeignKey до User уже существует.

От django.contrib.comments.models:

class Comment(BaseCommentAbstractModel):
    """
    A user comment about some object.
    """

    # Who posted this comment? If ``user`` is set then it was an authenticated
    # user; otherwise at least user_name should have been set and the comment
    # was posted by a non-authenticated user.
    user        = models.ForeignKey(User, verbose_name=_('user'),
                    blank=True, null=True, related_name="%(class)s_comments")
    user_name   = models.CharField(_("user's name"), max_length=50, blank=True)
    user_email  = models.EmailField(_("user's email address"), blank=True)
    user_url    = models.URLField(_("user's URL"), blank=True)

Кажется, я не могу понять, как настроить user. Если я использую комментарии как есть, даже если я аутентифицирован, мне по-прежнему требуются другие поля. Я предполагаю, что я должен переопределить форму и сделать это там? Кроме того, если я использую user, я должен игнорировать тот факт, что user_name, user_email и user_url будут пустыми, и просто брать эту информацию из связанной модели профиля, правильно?

Хотя в конце концов ответы могут быть довольно тривиальными, я просто удивлен, что об этом не написали и даже не обсудили.


person Bryan Veloso    schedule 22.07.2009    source источник


Ответы (6)


WordPress и другие системы делают это легкой задачей. Если вы вошли в систему, форма комментария должна просто «делать правильные вещи» и удалять поля имени / электронной почты / URL-адреса. Разве это не та тяжелая работа, которую должен выполнять за вас фреймворк?

Вместо того, чтобы танцевать с моделями подклассов для чего-то, что должно быть тривиально простым, я считаю, что проще создать форму вручную в шаблоне и указать необходимые значения скрытых полей. Это отлично работает для сайтов, которые принимают комментарии только от аутентифицированных пользователей:

{% if user.is_authenticated %}
{% get_comment_form for [object] as form %} 
<form action="{% comment_form_target %}" method="POST"> 
    {% csrf_token %}
    {{ form.comment }} 
    {{ form.honeypot }} 
    {{ form.content_type }} 
    {{ form.object_pk }} 
    {{ form.timestamp }} 
    {{ form.security_hash }} 
    <input type="hidden" name="next" value="{% url [the_view] [object].id %}" />
    <input type="submit" value="Add comment" id="id_submit" /> 
</form> 
{% else %}
    <p>Please <a href="{% url auth_login %}">log in</a> to leave a comment.</p>
{% endif %} 

Обратите внимание, что это оставит поле приманки видимым; вы захотите скрыть это в своем CSS:

#id_honeypot {
    visibility:hidden;
}

Если вы хотите включить комментарии для анонимных или аутентифицированных пользователей, замените строку auth_login выше стандартным вызовом формы комментариев.

person shacker    schedule 15.02.2010

Я рекомендую, когда у вас возникнет вопрос о внутренностях Django, взглянуть на источник.

Если мы посмотрим на начало post_comment view мы видим, что запрос POST скопирован, а адрес электронной почты и имя пользователя вставлены. Они по-прежнему необходимы (как показано в источник формы), поэтому эти данные должны быть либо введены в форму, либо их должен предоставить пользователь.

Чтобы ответить на ваш вопрос к Superjoe, представление прикрепляет пользователя к комментарию перед его сохранением (как показано ближе к концу представления post_comment).

person SmileyChris    schedule 28.07.2009
comment
Спасибо, Крис, по какой-то причине я продолжал смотреть на модели, а не на виды. Итак, технически я могу просто использовать exclude() в подклассовой форме и удалить поля имени, электронной почты и URL-адреса, и все будет работать как есть? Стоит попробовать, еще раз спасибо. :) - person Bryan Veloso; 01.08.2009
comment
Да, либо exclude = (...), либо вы могли бы выполнить логику в __init__ вашей формы, передав пользователя и вытащив поля, если пользователь аутентифицирован. - person SmileyChris; 03.08.2009

Используйте модель профиля для дополнительных данных учетной записи, помимо имени пользователя и пароля. Вы можете вызвать user.get_profile(), если включите эту строку в профиль:

user = models.ForeignKey(User, unique=True)

и эта строка в settings.py:

AUTH_PROFILE_MODULE = 'yourapp.Profile'
person andrewrk    schedule 22.07.2009
comment
Спасибо, хотя я знаю, как получить информацию из модели профиля. Вы случайно не знаете, как передать user в комментарий? - person Bryan Veloso; 22.07.2009

Во-первых, приложение для комментариев уже поддерживает как аутентифицированных, так и анонимных пользователей, поэтому я предполагаю, что вы хотите принимать комментарии только от аутентифицированных пользователей?

У Thejaswi Puthraya была серия статьи в его блоге обращаясь к этому. По сути, он предварительно заполняет поля name и email в форме комментария и заменяет их скрытыми полями, а затем определяет представление-оболочку вокруг post_comment, чтобы убедиться, что пользователь, публикующий комментарий, совпадает с вошедшим в систему пользователем, среди прочего. Выглядело довольно просто, хотя, может быть, немного утомительно.

Его блог, похоже, в настоящее время не работает... надеюсь, это временно.

person elo80ka    schedule 22.07.2009

Theju написал приложение для аутентифицированных комментариев — http://thejaswi.info/tech/blog/2009/08/04/reusable-app-authenticated-comments/

person Bryan Veloso    schedule 04.08.2009
comment
Сначала я проголосовал за этот ответ, но, поработав некоторое время с решением Theju, нашел его ограничивающим. Теперь я предпочитаю просто создавать форму вручную, вставляя все поля, которые ожидает Django (см. ниже). - person shacker; 16.02.2010

Согласно комментарию, это или-или: другие поля предназначены для использования, когда user не установлено. Вы проверили, что соответствующие столбцы определенно НЕ NULL? Они помечены как blank=True, что обычно означает required=False на уровне поля. Если вы действительно пробовали это, какие ошибки вы получаете?

person Vinay Sajip    schedule 22.07.2009