diff --git a/yatube/posts/models.py b/yatube/posts/models.py index 40695f2..ef0a977 100644 --- a/yatube/posts/models.py +++ b/yatube/posts/models.py @@ -35,7 +35,9 @@ class Post(CreatedModel): image = models.ImageField( "Картинка", upload_to='posts/', - blank=True + blank=True, + null=True, + help_text="Картинка, которая хорошо дополнит тест" ) class Meta(): @@ -50,7 +52,7 @@ class Comment(CreatedModel): post = models.ForeignKey( Post, on_delete=models.CASCADE, - verbose_name="Пост" + verbose_name="Пост", ) author = models.ForeignKey( User, @@ -70,7 +72,7 @@ class Follow(models.Model): User, on_delete=models.CASCADE, verbose_name="Пользователь", - related_name='follower' + related_name="follower" ) author = models.ForeignKey( User, @@ -84,9 +86,5 @@ class Meta: models.UniqueConstraint( fields=["user", "author"], name="unique_follow" - ), - models.CheckConstraint( - check=~models.Q( - user=models.F("author") - ), name="no_follow_yourself") + ) ] diff --git a/yatube/posts/tests/test_forms.py b/yatube/posts/tests/test_forms.py index d2a6fa2..89b7474 100644 --- a/yatube/posts/tests/test_forms.py +++ b/yatube/posts/tests/test_forms.py @@ -4,7 +4,6 @@ from django.conf import settings from django.contrib.auth import get_user_model -from django.core.cache import cache from django.core.files.uploadedfile import SimpleUploadedFile from django.test import Client, TestCase, override_settings from django.urls import reverse @@ -44,8 +43,6 @@ def setUp(self): self.guest_client = Client() - cache.clear() - def test_unauth_user_cant_publish_comment(self): form_data = { "post": self.post, @@ -72,6 +69,15 @@ def test_auth_user_can_publish_comment(self): follow=True ) self.assertEqual(Comment.objects.count(), 1) + comment = Comment.objects.first() + comment_attributes = { + comment.post: self.post, + comment.author: self.auth, + comment.text: form_data["text"] + } + for attribute, value in comment_attributes.items(): + with self.subTest(attribute=attribute): + self.assertEqual(attribute, value) self.assertEqual(response.status_code, HTTPStatus.OK) def test_unauth_user_cant_publish_post(self): diff --git a/yatube/posts/tests/test_views.py b/yatube/posts/tests/test_views.py index e841137..851dd30 100644 --- a/yatube/posts/tests/test_views.py +++ b/yatube/posts/tests/test_views.py @@ -207,40 +207,61 @@ def test_post_create_edit_page_show_correct_context(self): def test_index_cache(self): """Проверка кеширования главной страницы.""" - def get_page_obj(self): - responce = self.authorized_author.get(reverse("posts:index")) - return responce.content - - page_obj_before_delete_posts = get_page_obj(self) + page_obj_before_delete_posts = self.authorized_author.get( + reverse("posts:index")).content Post.objects.all().delete() - page_obj_after_delete_posts = get_page_obj(self) + page_obj_after_delete_posts = self.authorized_author.get( + reverse("posts:index")).content self.assertEqual(page_obj_before_delete_posts, page_obj_after_delete_posts) cache.clear() - page_obj_after_clear_cache = get_page_obj(self) - self.assertNotEqual(page_obj_after_delete_posts, + page_obj_after_clear_cache = self.authorized_author.get( + reverse("posts:index")).content + self.assertNotEqual(page_obj_before_delete_posts, page_obj_after_clear_cache) - def test_follow_index_page_show_correct_context_follow_unfollow(self): - """Авторизованный пользователь может подписываться на других - пользователей и удалять их из подписок. - Запись пользователя появляется в ленте тех, кто на него подписан - и не появляется в ленте тех, кто не подписан. - """ + def test_post_exists_at_followed(self): + """Пост появляется у тех, кто подписан.""" self.authorized_client.get( reverse("posts:profile_follow", kwargs={"username": self.auth})) - response = self.authorized_client.get(reverse("posts:follow_index")) posts = response.context["page_obj"] self.assertEqual(len(posts), 1) self.check_post(posts[0]) + def test_post_not_exists_at_no_followed(self): + """Пост не появляется у тех, кто не подписан.""" + response = self.authorized_client.get(reverse("posts:follow_index")) + self.assertEqual(len(response.context["page_obj"]), 0) + + def test_authorized_client_can_follow(self): + """Авторизованной пользователь может подписаться.""" + self.authorized_client.get( + reverse("posts:profile_follow", kwargs={"username": self.auth})) + + count_follows = self.auth.following.count() + self.assertEqual(count_follows, 1) + + follow = self.auth.following.get() + follow_attributes = { + follow.user: follow.user, + follow.author: follow.author, + } + for attribute, value in follow_attributes.items(): + with self.subTest(attribute=attribute): + self.assertEqual(attribute, value) + + def test_authorized_client_can_unfollow(self): + """Авторизованный пользователь может отписаться.""" + self.authorized_client.get( + reverse("posts:profile_follow", kwargs={"username": self.auth})) + self.authorized_client.get( reverse("posts:profile_unfollow", kwargs={"username": self.auth})) - response = self.authorized_client.get(reverse("posts:follow_index")) - self.assertEqual(len(response.context["page_obj"]), 0) + count_follows = self.auth.following.count() + self.assertEqual(count_follows, 0) diff --git a/yatube/posts/views.py b/yatube/posts/views.py index e209262..c6a58af 100644 --- a/yatube/posts/views.py +++ b/yatube/posts/views.py @@ -5,7 +5,7 @@ from django.views.decorators.cache import cache_page from .forms import CommentForm, PostForm -from .models import Comment, Follow, Group, Post, User +from .models import Follow, Group, Post, User CACHE_TIMEOUT_INDEX = 20 @@ -38,7 +38,8 @@ def group_posts(request, slug): def profile(request, username): author = get_object_or_404(User, username=username) posts = author.posts.select_related("author", "group") - following = author.following.exists() + following = (request.user.is_authenticated + and author.following.filter(user=request.user).exists()) context = { "author": author, "page_obj": paginate_page(request, posts), @@ -50,7 +51,7 @@ def profile(request, username): def post_detail(request, post_id): post = get_object_or_404(Post, pk=post_id) form = CommentForm(request.POST or None) - comments = Comment.objects.filter(post_id=post.pk) + comments = post.comments.select_related("author") if request.method == "POST" and form.is_valid(): add_comment(request, post_id=post.pk) context = { @@ -125,10 +126,12 @@ def follow_index(request): @login_required def profile_follow(request, username): - if request.user.username != username: - Follow.objects.update_or_create( - user=request.user, - author=get_object_or_404(User, username=username) + user = request.user + author = get_object_or_404(User, username=username) + if user != author: + Follow.objects.get_or_create( + user=user, + author=author ) return redirect("posts:follow_index") diff --git a/yatube/templates/core/403csrf.html b/yatube/templates/core/403csrf.html index 660bacc..72c97e6 100644 --- a/yatube/templates/core/403csrf.html +++ b/yatube/templates/core/403csrf.html @@ -1,4 +1,7 @@ {% extends "base.html" %} +{% block title %}Ошибка 403{% endblock %} {% block content %} -

Custom CSRF check error. 403

+

Доступ к запрошенному ресурсу запрещен

+

У Вас недостаточно прав для этого действия...

+ Идите на главную {% endblock %} \ No newline at end of file diff --git a/yatube/templates/core/404.html b/yatube/templates/core/404.html index 0d407c5..3617120 100644 --- a/yatube/templates/core/404.html +++ b/yatube/templates/core/404.html @@ -1,7 +1,7 @@ {% extends "base.html" %} -{% block title %}Custom 404{% endblock %} +{% block title %}Ошибка 404{% endblock %} {% block content %} -

Custom 404

+

O-o! Страница не найдена

Страницы с адресом {{ path }} не существует

Идите на главную {% endblock %} \ No newline at end of file