Сделаем так, чтобы зарегистрированные пользователи могли оставлять комментарии беспрепятственно, а гости должны были дополнительно ввести CAPTCHA. Так мы хоть как-то обезопасим сайт от атаки служб рассылки спама.
Установим библиотеку Django Simple Captcha:
pipenv install django-simple-captcha
Добавим в список зарегистрированных в проекте приложение captcha— программное
ядро этой библиотеки:
INSTALLED_APPS = [
...
'captcha',
]
И объявим в списке маршрутов уровня проекта (модуль urls.py пакета конфигурации)
маршрут, указывающий на это приложение:
urlpatterns = [
path('captcha/', include('captcha.urls')),
path('', include('main.urls')),
]
Код, объявляющий модель comment
class Comment(models.Model):
bb = models.ForeignKey(Bb, on_delete=models.CASCADE, verbose_name='Объявление')
author = models.CharField(max_length=30, verbose_name= 'Автор')
content = models.TextField(verbose_name='Содержание')
is_active = models.BooleanField(default=True, db_index=True, verbose_name='Выводить на экран?')
created_at = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Опубликован')
class Meta:
verbose_name_plural = 'Комментарии'
verbose_name = 'Комментарий'
ordering = ['created_at']
Объявим связанные С моделью Comment формы UserCommentForm И GuestCommentForm, в которые будут заносить комментарии, соответственно, зарегистрированные пользователи, выполнившие вход, и гости.
from captcha.fields import CaptchaField
from .models import Comment
class UserCommentForm(forms.ModelForm):
class Meta:
model = Comment
exclude = ('is_active',)
widgets = {'bb': forms.HiddenInput}
class GuestCommentForm (forms. ModelForm):
captcha = CaptchaField(label='Введите текст с картинки',
error_messages={'invalid': 'Неправильный текст'})
class Meta:
model = Comment
exclude = ('is_active',)
widgets = {'bb': forms.HiddenInput}
Теперь необходимо существенно обновить код контроллера-функции detail(), реализовав в нем вывод комментариев и добавление нового комментария.
from .models import Comment
from .forms import UserCommentForm, GuestCommentForm
def detail(request, rubric_pk, pk):
bb = Bb.objects.get(pk=pk)
ais = bb.additionalimage_set.all()
comments = Comment.objects.filter(bb=pk, is_active=True)
initial = {'bb': bb.pk}
if request.user.is_authenticated:
initial['author'] = request.user.username
form_class = UserCommentForm
else:
form_class = GuestCommentForm
form = form_class(initial=initial)
if request.method == 'POST':
c_form = form_class(request.POST)
if c_form.is_valid():
c_form.save()
messages.add_message(request, messages.SUCCESS, 'Комментарии добавлен')
else:
form = c_form
messages.add_message(request, messages.WARNING, 'Комментарий не добавлен')
context = {'bb': bb, 'ais': ais, 'comments': comments, 'form': form}
return render(request, ’main/detail.html’, context)
В шаблоне main\detail.html отыщем тег шаблонизатора block content … endblock и вставим перед закрывающим тегом код, выводящий комментарии:
...
{% load bootstrap4 %}
...
{% block content %}
...
<h4 class="mt-5">Новый комментарий</h4>
<form method="post">
{% csrf_token %}
{% bootstrap_form form layout='horizontal' %}
{% buttons submi t='Добавить' %} {% endbuttons %}
</form>
{% if comments %}
<div class="mt-5">
{% for comment in comments %}
<div class="my-2 p-2 border">
<h5>{{ comment.author }}</h5>
<p>{{ comment.content }}</p>
<p class="text-right font-italic">{{ comment.created_at }}</p>
</div>
{% endfor %}
</div>
{% endif %}
{% endblock %}