diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b2bfccc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + "./mainapp", + "-p", + "test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true +} \ No newline at end of file diff --git a/001_courses.json b/001_courses.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/001_courses.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/authapp/migrations/0002_alter_customuser_options.py b/authapp/migrations/0002_alter_customuser_options.py new file mode 100644 index 0000000..bbd1ccf --- /dev/null +++ b/authapp/migrations/0002_alter_customuser_options.py @@ -0,0 +1,17 @@ +# Generated by Django 4.0.4 on 2022-06-06 12:30 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('authapp', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='customuser', + options={'verbose_name': 'user', 'verbose_name_plural': 'users'}, + ), + ] diff --git a/config/pytest.ini b/config/pytest.ini new file mode 100644 index 0000000..0d7b657 --- /dev/null +++ b/config/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +DJANGO_SETTINGS_MODULE = config.settings +python_files = tests.py \ No newline at end of file diff --git a/config/settings.py b/config/settings.py index 48a6d7a..4594d6d 100644 --- a/config/settings.py +++ b/config/settings.py @@ -49,6 +49,7 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', "debug_toolbar.middleware.DebugToolbarMiddleware", + 'django.middleware.locale.LocaleMiddleware', ] ROOT_URLCONF = 'config.urls' @@ -68,6 +69,7 @@ "mainapp.context_processors.example.simple_context_processor", "social_django.context_processors.backends", "social_django.context_processors.login_redirect", + ], 'libraries':{'email_to_link':'mainapp.context_processors.example'} @@ -122,6 +124,7 @@ TIME_ZONE = 'Europe/Moscow' USE_I18N = True +LOCALE_PATH = [BASE_DIR / 'locale'] USE_TZ = True diff --git a/config/urls.py b/config/urls.py index 8d3fc9b..d3e0b1e 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,6 +1,5 @@ from django.contrib import admin - from django.conf import settings from django.urls import path, include from django.views.generic import RedirectView @@ -9,6 +8,7 @@ urlpatterns = [ path('admin/', admin.site.urls), path("", RedirectView.as_view(url="mainapp/")), + path("i18n/", include("django.conf.urls.i18n")), path("mainapp/", include("mainapp.urls", namespace='mainapp')), path("authapp/", include("authapp.urls", namespace="authapp")), path("social_auth/", include("social_django.urls", namespace='social')) diff --git a/db.sqlite3 b/db.sqlite3 index f6e15d2..8dbbea0 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/fixtures/001_courses.json b/fixtures/001_courses.json new file mode 100644 index 0000000..54c7453 --- /dev/null +++ b/fixtures/001_courses.json @@ -0,0 +1,114 @@ +[ + { + "model": "mainapp.courses", + "pk": 1, + "fields": { + "name": "Курс_1", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 2, + "fields": { + "name": "Курс_2", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 3, + "fields": { + "name": "Курс_3", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 4, + "fields": { + "name": "Курс_4", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 5, + "fields": { + "name": "Курс_5", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 6, + "fields": { + "name": "Курс_6", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 7, + "fields": { + "name": "Курс_7", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } + { + "model": "mainapp.courses", + "pk": 8, + "fields": { + "name": "Курс_8", + "description": "описание", + "description_as_markdown": false, + "cost": "2000.00", + "cover": "no_image.svg", + "created": "2022-06-06T14:41:33.551Z", + "updated": "2022-06-06T14:41:33.551Z", + "deleted": false + } + } +] \ No newline at end of file diff --git a/fixtures/001_news.json b/fixtures/001_news.json new file mode 100644 index 0000000..c252810 --- /dev/null +++ b/fixtures/001_news.json @@ -0,0 +1 @@ +[{"model": "mainapp.news", "pk": 1, "fields": {"title": "Заголовок 1", "preambule": "вступлене", "body": "текст", "body_as_markdown": false, "created": "2022-06-06T12:32:34.332Z", "updated": "2022-06-06T12:32:34.332Z", "deleted": false}}, {"model": "mainapp.news", "pk": 2, "fields": {"title": "заголовок 2", "preambule": "вступление", "body": "текст", "body_as_markdown": false, "created": "2022-06-06T12:32:54.839Z", "updated": "2022-06-06T12:32:54.839Z", "deleted": false}}] \ No newline at end of file diff --git a/fixtures/001_user.json b/fixtures/001_user.json new file mode 100644 index 0000000..702b520 --- /dev/null +++ b/fixtures/001_user.json @@ -0,0 +1,42 @@ +[ + { + "model": "authapp.customuser", + "pk": 1, + "fields": { + "password": "pbkdf2_sha256$320000$PIuI7VUQVdk60J6ijcX2KD$tRryChpq4Wt/reIEo3NONSeJqCj8HCI+P/71AJRML7k=", + "last_login": "2022-06-06T12:32:03.027Z", + "is_superuser": true, + "username": "test", + "first_name": "", + "last_name": "", + "age": null, + "avatar": "", + "email": "test@df.ua", + "is_staff": true, + "is_active": true, + "date_joined": "2022-06-02T13:28:07.406Z", + "groups": [], + "user_permissions": [] + } + }, + { + "model": "authapp.customuser", + "pk": 2, + "fields": { + "password": "pbkdf2_sha256$320000$pEp2GBrzmPB6kUInt71Wjj$pRCK/+xaM3LJhHS7oA0bNWqHI5UQT7twUfIuvLRB6Bs=", + "last_login": "2022-06-02T14:01:43.713Z", + "is_superuser": false, + "username": "test2", + "first_name": "jkhb", + "last_name": "kj", + "age": 20, + "avatar": "", + "email": "dgefdghdf@dfg.uf", + "is_staff": false, + "is_active": true, + "date_joined": "2022-06-02T13:59:28.263Z", + "groups": [], + "user_permissions": [] + } + } +] \ No newline at end of file diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..f8fa253 --- /dev/null +++ b/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-06 18:25+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: authapp/forms.py:55 +msgid "Please, enter a valid age!" +msgstr "" + +#: authapp/models.py:18 +msgid "username" +msgstr "" + +#: authapp/models.py:22 +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_only." +msgstr "" + +#: authapp/models.py:25 +msgid "A user with that username already exists." +msgstr "" + +#: authapp/models.py:28 +msgid "first name" +msgstr "" + +#: authapp/models.py:29 +msgid "last name" +msgstr "" + +#: authapp/models.py:35 +msgid "email address" +msgstr "" + +#: authapp/models.py:39 +msgid "A user with that email address already exists." +msgstr "" + +#: authapp/models.py:43 +msgid "staff status" +msgstr "" + +#: authapp/models.py:46 +msgid "Designates whether the user can log into this admin site." +msgstr "" + +#: authapp/models.py:50 +msgid "active" +msgstr "" + +#: authapp/models.py:53 +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +#: authapp/models.py:57 +msgid "date joined" +msgstr "" + +#: authapp/models.py:64 +msgid "user" +msgstr "" + +#: authapp/models.py:65 +msgid "users" +msgstr "" + +#: authapp/views.py:18 +msgid "" +"Вход совершен
Привет, {name if name else self.request.user.get_username()}" +msgstr "" + +#: authapp/views.py:30 +msgid "Досвидания!" +msgstr "" diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..2019f57 --- /dev/null +++ b/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-06 12:56+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +#: authapp/forms.py:55 +msgid "Please, enter a valid age!" +msgstr "Пожалуйста введите правильный возраст" + +#: authapp/models.py:18 +msgid "username" +msgstr "Имя_пользователя" + +#: authapp/models.py:22 +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_only." +msgstr "Необходимо 150 менее симвоолов буквы и цифры возможны символы @/./+/-/ " + +#: authapp/models.py:25 +msgid "A user with that username already exists." +msgstr "Выбраное имя пользователя уже существует" + +#: authapp/models.py:28 +msgid "first name" +msgstr "Имя" + +#: authapp/models.py:29 +msgid "last name" +msgstr "Фамилия" + +#: authapp/models.py:35 +msgid "email address" +msgstr "Почта" + +#: authapp/models.py:39 +msgid "A user with that email address already exists." +msgstr "Пользователь с такой почтой уже существует" + +#: authapp/models.py:43 +msgid "staff status" +msgstr "служебный статус" + +#: authapp/models.py:46 +msgid "Designates whether the user can log into this admin site." +msgstr "" + +#: authapp/models.py:50 +msgid "active" +msgstr "актв" + +#: authapp/models.py:53 +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +#: authapp/models.py:57 +msgid "date joined" +msgstr "" + +#: authapp/models.py:64 +msgid "user" +msgstr "Пользователь" + +#: authapp/models.py:65 +msgid "users" +msgstr "Пользователи" + +#: authapp/views.py:18 +msgid "" +"Вход совершен
Привет, {name if name else self.request.user.get_username()}" +msgstr "" + +#: authapp/views.py:30 +msgid "Досвидания!" +# msgstr "Досвидания" diff --git a/mainapp/locale/en/LC_MESSAGES/django.po b/mainapp/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..e3827e2 --- /dev/null +++ b/mainapp/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-06 18:25+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: mainapp/admin.py:35 mainapp/models.py:93 +msgid "Course" +msgstr "Course" + +#: mainapp/admin.py:40 +msgid "Mark deleted" +msgstr "deleted" + +#: mainapp/forms.py:25 +msgid "Enter your message" +msgstr "enter message" + +#: mainapp/forms.py:25 +msgid "Message" +msgstr "Сообщение" + +#: mainapp/models.py:16 mainapp/models.py:17 +#: mainapp/templates/includes/head_menu.html:17 +msgid "Новости" +msgstr "News" + +#: mainapp/models.py:92 +msgid "User" +msgstr "User" + +#: mainapp/models.py:94 +msgid "No feedback" +msgstr "no feedback" + +#: mainapp/models.py:94 +msgid "Feedback" +msgstr "Feedback" + +#: mainapp/models.py:97 +msgid "Rating" +msgstr "Rating" + +#: mainapp/templates/includes/head_menu.html:22 +msgid "Курсы" +msgstr "Course" + +#: mainapp/templates/includes/head_menu.html:29 +msgid "Контакты" +msgstr "Contacts" + +#: mainapp/templates/includes/head_menu.html:52 +msgid "Выход" +msgstr "Exit" + +#: mainapp/templates/includes/head_menu.html:54 +msgid "Вход" +msgstr "Enter" + +#: mainapp/views.py:145 +msgid "Message sended" +msgstr "sended" + +#: mainapp/views.py:155 +msgid "You can send only one message per 5 minutes" +msgstr "wait 5 minutes" diff --git a/mainapp/locale/ru/LC_MESSAGES/django.po b/mainapp/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..f266b83 --- /dev/null +++ b/mainapp/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-06 12:56+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" +#: mainapp/admin.py:35 mainapp/models.py:93 +msgid "Course" +msgstr "" + +#: mainapp/admin.py:40 +msgid "Mark deleted" +msgstr "" + +#: mainapp/forms.py:25 +msgid "Enter your message" +msgstr "" + +#: mainapp/forms.py:25 +msgid "Message" +msgstr "" + +#: mainapp/models.py:16 mainapp/models.py:17 +msgid "Новости" +msgstr "" + +#: mainapp/models.py:92 +msgid "User" +msgstr "" + +#: mainapp/models.py:94 +msgid "No feedback" +msgstr "" + +#: mainapp/models.py:94 +msgid "Feedback" +msgstr "" + +#: mainapp/models.py:97 +msgid "Rating" +msgstr "" + +#: mainapp/templates/includes/head_menu.html:15 +msgid "News" +msgstr "" + +#: mainapp/templates/includes/head_menu.html:20 +msgid "Courses" +msgstr "" + +#: mainapp/templates/includes/head_menu.html:27 +msgid "Contacts" +msgstr "" + +#: mainapp/templates/includes/head_menu.html:50 +msgid "logout" +msgstr "" + +#: mainapp/templates/includes/head_menu.html:52 +msgid "login" +msgstr "" + +#: mainapp/views.py:143 +msgid "Message sended" +msgstr "" + +#: mainapp/views.py:153 +msgid "You can send only one message per 5 minutes" +msgstr "" diff --git a/mainapp/templates/includes/base.html b/mainapp/templates/includes/base.html index 8ef3310..52e1172 100644 --- a/mainapp/templates/includes/base.html +++ b/mainapp/templates/includes/base.html @@ -1,5 +1,6 @@ {% load static %} + diff --git a/mainapp/templates/includes/head_menu.html b/mainapp/templates/includes/head_menu.html index 39c5a53..c6a8408 100644 --- a/mainapp/templates/includes/head_menu.html +++ b/mainapp/templates/includes/head_menu.html @@ -1,3 +1,5 @@ +{% load static i18n %} + \ No newline at end of file diff --git a/mainapp/templates/includes/paginator.html b/mainapp/templates/includes/paginator.html new file mode 100644 index 0000000..0f32159 --- /dev/null +++ b/mainapp/templates/includes/paginator.html @@ -0,0 +1,19 @@ +
+ +
\ No newline at end of file diff --git a/mainapp/templates/mainapp/courses_list.html b/mainapp/templates/mainapp/courses_list.html index b30bce0..ee8b88f 100644 --- a/mainapp/templates/mainapp/courses_list.html +++ b/mainapp/templates/mainapp/courses_list.html @@ -10,95 +10,39 @@ -
-
+ {% include 'includes/paginator.html' %} diff --git a/mainapp/templates/mainapp/news.html b/mainapp/templates/mainapp/news.html index f723a66..65481cd 100644 --- a/mainapp/templates/mainapp/news.html +++ b/mainapp/templates/mainapp/news.html @@ -74,15 +74,5 @@
{% endif %} -
- -
+{% include 'includes/paginator.html' %} {% endblock content %} \ No newline at end of file diff --git a/mainapp/templates/mainapp/news_list.html b/mainapp/templates/mainapp/news_list.html index 4650757..a80df27 100644 --- a/mainapp/templates/mainapp/news_list.html +++ b/mainapp/templates/mainapp/news_list.html @@ -42,6 +42,11 @@
{% endfor %} + + + + +
@@ -71,15 +76,7 @@
{% endif %}
-
- -
+ + + {% endblock content %} \ No newline at end of file diff --git a/mainapp/tests.py b/mainapp/tests.py index 7ce503c..6ed5782 100644 --- a/mainapp/tests.py +++ b/mainapp/tests.py @@ -1,3 +1,94 @@ -from django.test import TestCase +from django.test import TestCase, Client +from django.urls import reverse +from http import HTTPStatus +from mainapp import models as mainapp_models -# Create your tests here. +class TestNewsPage(TestCase): + fixtures = ( + "fixtures/001_user_admin.json", + "fixtures/001_news.json", + ) + + def setUp(self): + super().setUp() + self.client_with_auth = Client() + path_auth = reverse("authapp:login") + self.client_with_auth.post( + path_auth, data={"username": "test", "password": "test"} + ) + + def test_page_open_list(self): + path = reverse("mainapp:news") + result = self.client.get(path) + self.assertEqual(result.status_code, HTTPStatus.OK) + + def test_page_open_detail(self): + news_obj = mainapp_models.News.objects.first() + path = reverse("mainapp:news_detail", args=[news_obj.pk]) + result = self.client.get(path) + self.assertEqual(result.status_code, HTTPStatus.OK) + + def test_page_open_crete_deny_access(self): + path = reverse("mainapp:news_create") + result = self.client.get(path) + self.assertEqual(result.status_code, HTTPStatus.FOUND) + + def test_page_open_crete_by_admin(self): + path = reverse("mainapp:news_create") + result = self.client_with_auth.get(path) + self.assertEqual(result.status_code, HTTPStatus.OK) + + def test_create_in_web(self): + counter_before = mainapp_models.News.objects.count() + path = reverse("mainapp:news_create") + self.client_with_auth.post( + path, + data={ + "title": "NewTestNews001", + "preambule": "NewTestNews001", + "body": "NewTestNews001", + }, + ) + self.assertGreater(mainapp_models.News.objects.count(),counter_before) + + def test_page_open_update_deny_access(self): + news_obj = mainapp_models.News.objects.first() + path = reverse("mainapp:news_update", args=[news_obj.pk]) + result = self.client.get(path) + self.assertEqual(result.status_code, HTTPStatus.FOUND) + + def test_page_open_update_by_admin(self): + news_obj = mainapp_models.News.objects.first() + path = reverse("mainapp:news_update", args=[news_obj.pk]) + result = self.client_with_auth.get(path) + self.assertEqual(result.status_code, HTTPStatus.OK) + + def test_update_in_web(self): + new_title = "NewTestTitle001" + news_obj = mainapp_models.News.objects.first() + self.assertNotEqual(news_obj.title, new_title) + path = reverse("mainapp:news_update", args=[news_obj.pk]) + result = self.client_with_auth.post( + path, + data={ + "title": new_title, + "preambule": news_obj.preambule, + "body": news_obj.body, + }, + ) + self.assertEqual(result.status_code, HTTPStatus.FOUND) + news_obj.refresh_from_db() + self.assertEqual(news_obj.title, new_title) + + def test_delete_deny_access(self): + news_obj = mainapp_models.News.objects.first() + path = reverse("mainapp:news_delete", args=[news_obj.pk]) + result = self.client.post(path) + self.assertEqual(result.status_code, HTTPStatus.FOUND) + + def test_delete_in_web(self): + news_obj = mainapp_models.News.objects.first() + path = reverse("mainapp:news_delete", args=[news_obj.pk]) + self.client_with_auth.post(path) + news_obj.refresh_from_db() + self.assertTrue(news_obj.deleted) \ No newline at end of file diff --git a/mainapp/urls.py b/mainapp/urls.py index f5495e5..b4d8b9c 100644 --- a/mainapp/urls.py +++ b/mainapp/urls.py @@ -1,4 +1,4 @@ -from django.urls import path +from django.urls import path, include from mainapp import views from mainapp.apps import MainappConfig from django.views.decorators.cache import cache_page @@ -7,12 +7,13 @@ urlpatterns = [ path("", views.MainPageView.as_view(), name="main_page"), - path("news/", views.NewsListView.as_view(), name="news"), + path("news/", views.newsListView, name="news"), path("news/create/", views.NewsCreateView.as_view(), name="news_create"), path("news//detail",views.NewsDetailView.as_view(),name="news_detail",), path("news//update",views.NewsUpdateView.as_view(),name="news_update",), path("news//delete",views.NewsDeleteView.as_view(),name="news_delete",), - path("courses/",cache_page(60 * 5)(views.CoursesListView.as_view()),name="courses",), + # path("courses/",cache_page(60 * 5)(views.CoursesListView.as_view()),name="courses",), + path("courses/",views.CoursesListView.as_view(),name="courses",), path("courses//",views.CoursesDetailView.as_view(),name="courses_detail",), path("course_feedback/",views.CourseFeedbackFormProcessView.as_view(),name="course_feedback",), path("contacts/", views.ContactsPageView.as_view(), name="contacts"), diff --git a/mainapp/views.py b/mainapp/views.py index 1b79df4..f922edc 100644 --- a/mainapp/views.py +++ b/mainapp/views.py @@ -19,6 +19,8 @@ from django.utils.translation import gettext_lazy as _ from mainapp import forms as mainapp_forms from mainapp import models as mainapp_models +from django.core.paginator import Paginator +from django.shortcuts import render @@ -45,13 +47,26 @@ def get_context_data(self, pk=None, **kwargs): return context -class NewsListView(ListView): - template_name = 'mainapp/news.html' +# class NewsListView(ListView): +# template_name = 'mainapp/news.html' +# model = mainapp_models.News +# paginate_by = 5 + +# def get_queryset(self): +# return super().get_queryset().filter(deleted=False) + +def newsListView(request): model = mainapp_models.News - paginate_by = 5 + contact_list = model.objects.all() + paginator = Paginator(contact_list, 5) + + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) + return render(request, 'mainapp/news.html', {'page_obj': page_obj}) + + + - def get_queryset(self): - return super().get_queryset().filter(deleted=False) class NewsCreateView(PermissionRequiredMixin, CreateView): model = mainapp_models.News @@ -76,10 +91,12 @@ class NewsDeleteView(PermissionRequiredMixin, DeleteView): class CoursesListView(TemplateView): template_name = "mainapp/courses_list.html" + # paginate_by = 5 def get_context_data(self, **kwargs): context = super(CoursesListView, self).get_context_data(**kwargs) - context["objects"] = mainapp_models.Courses.objects.all()[:7] + context["objects"] = mainapp_models.Courses.objects.all() + return context class CoursesDetailView(TemplateView): diff --git a/management/commands/my_command.py b/management/commands/my_command.py new file mode 100644 index 0000000..e27cb8e --- /dev/null +++ b/management/commands/my_command.py @@ -0,0 +1,11 @@ +from django.core.management import BaseCommand, call_command + +class Command(BaseCommand): + help = ( + 'Это моя тестовая команда\n' + '--locale=ru -- no-location' + ) + + def handle(self, *args: Any, **options: Any): + call_command('makemassages', '--locale=ru', '--ignore=env', '--no-location') + return super().handle(*args, **options) \ No newline at end of file