diff --git a/blog/blog/settings.py b/blog/blog/settings.py index 5d1076c..b7a7e92 100644 --- a/blog/blog/settings.py +++ b/blog/blog/settings.py @@ -40,6 +40,7 @@ INSTALLED_APPS = [ "django.contrib.staticfiles", "posts.apps.PostConfig", "mainpage.apps.MainpageConfig", + "comments.apps.CommentsConfig", ] MIDDLEWARE = [ diff --git a/blog/comments/__init__.py b/blog/comments/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/comments/admin.py b/blog/comments/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/blog/comments/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/blog/comments/apps.py b/blog/comments/apps.py new file mode 100644 index 0000000..a90cc97 --- /dev/null +++ b/blog/comments/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CommentsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'comments' diff --git a/blog/comments/eyerest/Main b/blog/comments/eyerest/Main new file mode 100644 index 0000000..2186f1f --- /dev/null +++ b/blog/comments/eyerest/Main @@ -0,0 +1 @@ +((1 (((min-height . 8) (min-width . 20) (min-height-ignore . 6) (min-width-ignore . 8) (min-height-safe . 2) (min-width-safe . 4) (min-pixel-height . 160) (min-pixel-width . 180) (min-pixel-height-ignore . 120) (min-pixel-width-ignore . 72) (min-pixel-height-safe . 40) (min-pixel-width-safe . 36)) hc (pixel-width . 2044) (pixel-height . 1080) (total-width . 227) (total-height . 54) (normal-height . 1.0) (normal-width . 1.0) (combination-limit) (vc (pixel-width . 1017) (pixel-height . 1080) (total-width . 113) (total-height . 54) (normal-height . 1.0) (normal-width . 0.4975538160469667) (combination-limit) (leaf (pixel-width . 1017) (pixel-height . 540) (total-width . 113) (total-height . 27) (normal-height . 0.5) (normal-width . 1.0) (buffer "20220325142556-дневник_2022.org" (selected) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 72876) (start . 72360)) (prev-buffers ("20220409000136-вяленая_курица_джерки.org" 1 108) ("gui-config.org" 49463 49914))) (leaf (last . t) (pixel-width . 1017) (pixel-height . 540) (total-width . 113) (total-height . 27) (normal-height . 0.5) (normal-width . 1.0) (buffer "20220409000136-вяленая_курица_джерки.org" (selected) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 108) (start . 1)) (next-buffers "20220325142556-дневник_2022.org") (prev-buffers ("20220325142556-дневник_2022.org" 1 72377) ("20220409000136-вяленая_курица_джерки.org" 1 108)))) (vc (last . t) (pixel-width . 1027) (pixel-height . 1080) (total-width . 114) (total-height . 54) (normal-height . 1.0) (normal-width . 0.5024461839530333) (combination-limit) (leaf (pixel-width . 1027) (pixel-height . 540) (total-width . 114) (total-height . 27) (normal-height . 0.5) (normal-width . 1.0) (buffer "20220330104048-благоволительницы_джонатан_литтелл.org" (selected) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 1221) (start . 1)) (prev-buffers ("20220409000136-вяленая_курица_джерки.org" 1 108))) (leaf (last . t) (pixel-width . 1027) (pixel-height . 540) (total-width . 114) (total-height . 27) (normal-height . 0.5) (normal-width . 1.0) (buffer "20220408212219-jagten_2012.org" (selected . t) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 96) (start . 1)) (prev-buffers ("20220330104048-благоволительницы_джонатан_литтелл.org" 1 247))))) "personal") (2 (((min-height . 4) (min-width . 57) (min-height-ignore . 3) (min-width-ignore . 12) (min-height-safe . 1) (min-width-safe . 6) (min-pixel-height . 80) (min-pixel-width . 513) (min-pixel-height-ignore . 60) (min-pixel-width-ignore . 108) (min-pixel-height-safe . 20) (min-pixel-width-safe . 54)) hc (pixel-width . 2043) (pixel-height . 1080) (total-width . 227) (total-height . 54) (normal-height . 1.0) (normal-width . 1.0) (combination-limit) (leaf (pixel-width . 333) (pixel-height . 1080) (total-width . 37) (total-height . 54) (normal-height . 1.0) (normal-width . 0.16299559471365643) (parameters (window-side . left) (window-slot . 0)) (buffer " *Treemacs-Scoped-Buffer-#*" (selected) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated . t) (point . 743) (start . 418))) (hc (last . t) (pixel-width . 1710) (pixel-height . 1080) (total-width . 190) (total-height . 54) (normal-height . 1.0) (normal-width . 0.8370044052863436) (combination-limit . t) (leaf (pixel-width . 855) (pixel-height . 1080) (total-width . 95) (total-height . 54) (normal-height . 1.0) (normal-width . 0.5) (buffer "models.py" (selected . t) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 430) (start . 1)) (prev-buffers ("*scratch*" 1 153) ("gui-config.org" 12662 49814))) (leaf (last . t) (pixel-width . 855) (pixel-height . 1080) (total-width . 95) (total-height . 54) (normal-height . 1.0) (normal-width . 0.5) (buffer "models.py" (selected) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 846) (start . 1)) (prev-buffers ("models.py" 1 846) ("models.py" 1 792) ("models.py" 1 61))))) "") (3 (((min-height . 4) (min-width . 10) (min-height-ignore . 3) (min-width-ignore . 4) (min-height-safe . 1) (min-width-safe . 2) (min-pixel-height . 80) (min-pixel-width . 90) (min-pixel-height-ignore . 60) (min-pixel-width-ignore . 36) (min-pixel-height-safe . 20) (min-pixel-width-safe . 18)) leaf (pixel-width . 2043) (pixel-height . 1080) (total-width . 227) (total-height . 54) (normal-height . 1.0) (normal-width . 1.0) (buffer "20210616121338-django.org" (selected . t) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 6700) (start . 1))) "") (4 (((min-height . 4) (min-width . 10) (min-height-ignore . 3) (min-width-ignore . 4) (min-height-safe . 1) (min-width-safe . 2) (min-pixel-height . 80) (min-pixel-width . 90) (min-pixel-height-ignore . 60) (min-pixel-width-ignore . 36) (min-pixel-height-safe . 20) (min-pixel-width-safe . 18)) leaf (pixel-width . 2043) (pixel-height . 1080) (total-width . 227) (total-height . 54) (normal-height . 1.0) (normal-width . 1.0) (buffer "gui-config.org" (selected . t) (hscroll . 0) (fringes 0 0 nil nil) (margins 1 . 1) (scroll-bars nil 0 t nil 0 t nil) (vscroll . 0) (dedicated) (point . 39115) (start . 11896)) (prev-buffers ("20210331101333-теги_для_hugo.org" 1 1) ("*scratch*" 1 1) ("gui-config.org" 12662 49814))) "")) \ No newline at end of file diff --git a/blog/comments/migrations/0001_initial.py b/blog/comments/migrations/0001_initial.py new file mode 100644 index 0000000..568a138 --- /dev/null +++ b/blog/comments/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# Generated by Django 4.0.3 on 2022-04-09 12:38 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('posts', '0003_alter_post_options'), + ] + + operations = [ + migrations.CreateModel( + name='CommentAuthor', + 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='Хеш секрета')), + ], + ), + 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()), + ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='posts.post')), + ], + ), + ] diff --git a/blog/comments/migrations/0002_alter_comment_reply.py b/blog/comments/migrations/0002_alter_comment_reply.py new file mode 100644 index 0000000..cc7f019 --- /dev/null +++ b/blog/comments/migrations/0002_alter_comment_reply.py @@ -0,0 +1,18 @@ +# 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/migrations/__init__.py b/blog/comments/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/comments/models.py b/blog/comments/models.py new file mode 100644 index 0000000..a0cfacd --- /dev/null +++ b/blog/comments/models.py @@ -0,0 +1,26 @@ +from django.db import models +from posts.models import Post + + +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.IntegerField(null=True) + comment_text = models.TextField() + date = models.DateTimeField() + + +class CommentAuthor(models.Model): + """Валидация автора коммента. + + Если коментатор оставил секретную фразу, то от нее вычисляется + хеш, который сравнивается с тем, который есть в базе для этого + сочетания author_name:hash. + + """ + + author_name = models.CharField("Имя автора", max_length=60) + author_secret_hash = models.CharField("Хеш секрета", max_length=256) diff --git a/blog/comments/tests.py b/blog/comments/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/blog/comments/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/blog/comments/views.py b/blog/comments/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/blog/comments/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/blog/posts/admin.py b/blog/posts/admin.py index 0bef769..81dc7d8 100644 --- a/blog/posts/admin.py +++ b/blog/posts/admin.py @@ -5,4 +5,7 @@ from .models import Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): - fields = ("title", "text", "pub_date") + fieldsets = ( + ("Основное", {"classes": ("wide",), "fields": ("title", "text")}), + ("Дополнительно", {"classes": ("collapse",), "fields": ("pub_date",)}), + ) diff --git a/blog/posts/templates/posts/post.html b/blog/posts/templates/posts/post.html index ab042b8..beb537d 100644 --- a/blog/posts/templates/posts/post.html +++ b/blog/posts/templates/posts/post.html @@ -17,6 +17,14 @@
Опубликован: {{ post.pub_date | date:'Y-m-d, H:i' }}
{{ post.text }}
+
+

Комменты

+ {% for comment in comments %} +

{{ comment.author_name }}

+

{{ comment.comment_text }}

+
+ {% endfor %} + {% endautoescape %} diff --git a/blog/posts/views.py b/blog/posts/views.py index 6e79911..de993e5 100644 --- a/blog/posts/views.py +++ b/blog/posts/views.py @@ -2,6 +2,7 @@ from django.shortcuts import render, get_object_or_404 from django.http import HttpResponse from .models import Post +from comments.models import Comment import re @@ -16,5 +17,5 @@ def detail(request, post_id): """Страница с просмотром поста.""" # вынести отсюда все. Также надо обработать текст поста тут. post = get_object_or_404(Post, pk=post_id) - - return render(request, "posts/post.html", {"post": post}) + comments = post.comment_set.all() + return render(request, "posts/post.html", {"post": post, "comments": comments})