Давно хотел победить спам, приходящий в комментарии на моём сайте. Беглый гуглопоиск выдал только варианты с Акисметом от Романа Ворушина, а также намеки на другие варианты с модерацией.
Но так как Акисмет меня не впечатлил (не люблю прикручивать то что не контролирую полностью), пришлось смотреть в сторону написания своего приложения с комментариями. Ранее не хотел этого делать, поскольку считал изобретение велосипеда делом неправильным, но рост спама вынудил и я приступил к изучению Django documentation.
Вот тут то меня и посетило прозрение. Оказывается я заблуждался в том, что для кастомизации комментариев придется полностью писать своё приложение. Это не так.
По факту мы конечно создадим приложение, но только для добавления своего поля с логикой в форму комментариев и модель комментариев. А проделать это можно элементарным наследованием.
Ход моих действий по шагам:
1. Создаем приложение. Например mycomments.
2. Пишем "добавку" к модели комментариев в /mycomments/models.py
# -*- coding:utf-8 -*-
from django.db import models
from django.contrib.comments.models import Comment
from django.contrib import admin
#Класс наследник модели комментариев
class CommentWithQuest(Comment):
#Поле которое мы добавляем.
#В моём случае оно будет хранить ответы комментаторов на вопросы.
myquestion = models.CharField(max_length=150)
class Meta:
ordering = ('-submit_date',)
verbose_name = ('Комментарий')
verbose_name_plural = ('Комментарии')
class CommentWithQuestAdmin(admin.ModelAdmin):
list_display = ('user_name',
'submit_date',
'ip_address',
'is_public',
'is_removed',
'id')
search_fields = ('user_name', 'ip_address')
list_filter = ('is_public', 'is_removed', 'submit_date')
admin.site.register(CommentWithQuest, CommentWithQuestAdmin)
3. Теперь колдуем над формой в /mycomments/forms.py
# -*- coding:utf-8 -*-
import random
from django import forms
from mycomments.models import CommentWithQuest
from django.contrib.comments.forms import CommentForm
class CommentFormWithQuest(CommentForm):#Класс наследник класса формы комментариев.
#Где и как хранить вопросы дело Вашего вкуса, можно в файлах xml, можно в базе и т.д
#По этой причине свой вариант хранения я исключил и источник конкретезировать не буду.
qlen = ... #Получаем количество вопросов из источника
r = random.randrange(1,qlen,1) #Определяем номер вопроса для вывода
q = ... #Получаем из источника (вопрос, ответ) например в виде списка
myquestion = forms.CharField(max_length=20, label=( q[0].encode('utf-8')))
def get_comment_model(self):
return CommentWithQuest
def clean_myquestion(self):
value = self.cleaned_data["myquestion"]
value = value.lower()
if value != self.q[1]: #Проверяем ответ комментатора.
raise forms.ValidationError(u'Ваш ответ "%s" не верен. \
Попробуйте еще раз.' % value)
return value
#Прикручиваем все ранее написанное к форме родителю
def get_comment_create_data(self):
data = super(CommentFormWithQuest, self).get_comment_create_data()
data['myquestion'] = self.cleaned_data['myquestion']
return data
4. Вносим наше приложение в settings.py и указыаваем, что теперь будет вместо comments обрабатывать комментарии
INSTALLED_APPS = (
...
'mycomments',
...
)
COMMENTS_APP = 'mycomments'
5. Выполняем syncdb. Будьте внимательны этот шаг надо выполнять перед следующим, иначе получим ошибку базы данных.
6. Корректируем /mycomments/__init__.py
from mycomments.models import CommentWithQuest
from mycomments.forms import CommentFormWithQuest
def get_model():
return CommentWithQuest
def get_form():
return CommentFormWithQuest
7. Перегружаем наш проект и получаем комментарии с вопросом.
Такие комментарии работают на моём сайте. (Дополнительно организована премодерация всех ссылок)
К плюсам такого подхода могу смело добавить возможность фильтрации комментаторов сложностью вопросов. Таким образом Вы можете ограничить круг лиц, комментирующих ваши посты. Полезно для полузакрытых сообществ с высокими требованиями по знаниям в конкретных областях.
К относительным минусам - сырость кода. В связи с этим прошу высказывать замечания и предложения. Возможно все это реально написать красивее. Расскажите мне как и я исправлюсь. ;)
P.S. Так как в нашем деле без бубнотанцев ничего не проходит, отмечу ряд тонкостей для прикручивания на живой проект.
- В источнике вопросов должен быть хотя бы один вопрос, чтобы все это работало. Можно его добавлять по умолчанию в модель если Вы используете в качестве источника базу или в файлы хранилища.
- Если проект рабочий и уже содержит комментарии, то целесообразно заполнить вновь создаваемую модель CommentWithQuest данными (id комментария, ответ комментатора), взяв id уже существующих комментариев и добавив произвольный ответ комментатора.
Комментарии