{{ comment.reply.comment_text }}{% else %} -
[{{comment.id}}] {{ comment.author_name }} говорит:
++ {% if comment.is_anonym %} + {{ comment.nickname }} + {% else %} + {{ comment.author }} + {% endif %} + говорит:
{{ comment.comment_text }}
diff --git a/blog/comments/admin.py b/blog/comments/admin.py index 8c38f3f..f769d34 100644 --- a/blog/comments/admin.py +++ b/blog/comments/admin.py @@ -1,3 +1,7 @@ from django.contrib import admin +from .models import Comment -# Register your models here. + +@admin.register(Comment) +class CommentAdmin(admin.ModelAdmin): + pass diff --git a/blog/comments/migrations/0001_initial.py b/blog/comments/migrations/0001_initial.py index 568a138..c8ed12b 100644 --- a/blog/comments/migrations/0001_initial.py +++ b/blog/comments/migrations/0001_initial.py @@ -1,7 +1,8 @@ -# Generated by Django 4.0.3 on 2022-04-09 12:38 +# Generated by Django 4.0.3 on 2022-04-12 13:43 from django.db import migrations, models import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): @@ -18,19 +19,21 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('author_name', models.CharField(max_length=60, verbose_name='Имя автора')), - ('author_secret_hash', models.CharField(max_length=256, verbose_name='Хеш секрета')), + ('author_secret_hash', models.CharField(blank=True, max_length=256, null=True, verbose_name='Хеш секрета')), ], + options={ + 'unique_together': {('author_name', 'author_secret_hash')}, + }, ), migrations.CreateModel( name='Comment', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('author_name', models.CharField(max_length=60, verbose_name='имя автора')), - ('author_secret', models.CharField(blank=True, max_length=128, verbose_name='секретная строка')), - ('reply', models.IntegerField(blank=True)), ('comment_text', models.TextField()), - ('date', models.DateTimeField()), + ('date', models.DateTimeField(default=django.utils.timezone.now)), + ('author', models.ForeignKey(default='аноним', on_delete=django.db.models.deletion.CASCADE, to='comments.commentauthor')), ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='posts.post')), + ('reply', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='comments.comment')), ], ), ] diff --git a/blog/comments/migrations/0002_alter_comment_reply.py b/blog/comments/migrations/0002_alter_comment_reply.py deleted file mode 100644 index cc7f019..0000000 --- a/blog/comments/migrations/0002_alter_comment_reply.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.0.3 on 2022-04-09 13:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('comments', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='comment', - name='reply', - field=models.IntegerField(null=True), - ), - ] diff --git a/blog/comments/models.py b/blog/comments/models.py index b3912fa..d067d97 100644 --- a/blog/comments/models.py +++ b/blog/comments/models.py @@ -1,20 +1,8 @@ from django.db import models from posts.models import Post -from datetime import datetime from django.utils import timezone -class Comment(models.Model): - """Класс для комента.""" - - post = models.ForeignKey(Post, on_delete=models.CASCADE) - author_name = models.CharField("имя автора", max_length=60) - author_secret = models.CharField("секретная строка", max_length=128, blank=True) - reply = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True) - comment_text = models.TextField() - date = models.DateTimeField(default=timezone.now) - - class CommentAuthor(models.Model): """Валидация автора коммента. @@ -25,4 +13,47 @@ class CommentAuthor(models.Model): """ author_name = models.CharField("Имя автора", max_length=60) - author_secret_hash = models.CharField("Хеш секрета", max_length=256) + author_secret_hash = models.CharField( + "Хеш секрета", max_length=256, blank=True, null=True + ) + + def __str__(self): + return self.author_name + + class Meta: + # сделать сочетание полей уникальным + unique_together = (("author_name"),) + + def is_valid(self) -> bool: + if self.author_name and self.author_secret_hash: + return True + + +def get_anonym_id() -> int: + # тут бы еще проверку на существование такого пользователя. Если + # его нет - создать + obj, result = CommentAuthor.objects.get_or_create(author_name="Anonym") + return obj.id + + +class Comment(models.Model): + """Класс для комента.""" + + post = models.ForeignKey(Post, on_delete=models.CASCADE) + author = models.ForeignKey( + CommentAuthor, on_delete=models.CASCADE, default=get_anonym_id + ) + nickname = models.CharField("имя автора", max_length=60, blank=True, null=True) + reply = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True) + comment_text = models.TextField() + date = models.DateTimeField(default=timezone.now) + + def is_anonym(self) -> bool: + if self.author.id == get_anonym_id(): + return True + + else: + return False + + def __str__(self): + return f"{self.author_name}: {self.comment_text[:100]}" diff --git a/blog/comments/views.py b/blog/comments/views.py index 6c8caea..0c8a2b2 100644 --- a/blog/comments/views.py +++ b/blog/comments/views.py @@ -1,13 +1,17 @@ from django.shortcuts import render, reverse from posts.models import Post from django.http import Http404, HttpResponseRedirect -from .models import Comment +from .models import Comment, CommentAuthor from datetime import datetime from django.core.exceptions import ObjectDoesNotExist +from django.db import IntegrityError +import hashlib + +from typing import Union def leave_comment(request, post_id): - parent: Comment + parent: Union[Comment, None] try: post = Post.objects.get(id=post_id) @@ -30,10 +34,46 @@ def leave_comment(request, post_id): except ObjectDoesNotExist: parent = None - post.comment_set.create( - author_name=request.POST["name"], - comment_text=request.POST["text"], - reply=parent, - ) + # обработка секрета Перед записью в базу, нужно извлечь записи по + # нику. Где поле author_secret_hash не null, нужно вычислить и + # сравнить хэши; если хеши валидные то пишем в базу (еще раз уник не запишется); + + # если не передан секрет, то пользователь Anonym + # если секрет не совпал, то польозхватель Anonym + + author = get_or_create_author(request.POST["name"], request.POST["secret"]) + nickname = request.POST["name"] + + if not author: + post.comment_set.create( + nickname=nickname, + comment_text=request.POST["text"], + reply=parent, + ) + else: + post.comment_set.create( + author=author, + nickname=nickname, + comment_text=request.POST["text"], + reply=parent, + ) return HttpResponseRedirect(reverse("posts:detail", args=(post.id,))) + + +def get_or_create_author(name: str, secret: str) -> Union[CommentAuthor, None]: + + if secret == "": + return None + + hash = hashlib.md5(secret.encode("utf-8")).hexdigest() + + try: + author, result = CommentAuthor.objects.get_or_create( + author_name=name, author_secret_hash=hash + ) + except IntegrityError: + # если имя/хеш не совпадают, то игнорируем такого автора и отображаем ником + author = None + + return author diff --git a/blog/db.sqlite3 b/blog/db.sqlite3 index 31134cd..61d65d2 100644 Binary files a/blog/db.sqlite3 and b/blog/db.sqlite3 differ diff --git a/blog/posts/templates/posts/post.html b/blog/posts/templates/posts/post.html index 42f0755..fd009c8 100644 --- a/blog/posts/templates/posts/post.html +++ b/blog/posts/templates/posts/post.html @@ -1,5 +1,6 @@ {% extends 'base.html' %} {% load tz %} +{% load static %} {% block title %}{{ post.title }}{% endblock %} {% block content %} {% autoescape off %} @@ -17,44 +18,63 @@
Комменты
+[{{comment.id}}] {{ comment.author_name }} отвечает {{ comment.reply.author_name }}:
+{% if comment.is_anonym %} + {{ comment.nickname }} + {% else %} + {{ comment.author }} + {% endif %} + отвечает {{ comment.reply.author_name }}:
{% endfor %} -