From 237524be8e5da2930d9e3ac817c72daa6fe94228 Mon Sep 17 00:00:00 2001 From: SDE Date: Mon, 28 Aug 2023 18:05:50 +0300 Subject: [PATCH] 0.5.0 ArticlesApp --- ArticlesApp/__init__.py | 0 ArticlesApp/admin.py | 159 +++++++++++++++++++++++++ ArticlesApp/migrations/0001_initial.py | 103 ++++++++++++++++ ArticlesApp/migrations/__init__.py | 0 ArticlesApp/models.py | 37 ++++++ ArticlesApp/tests.py | 16 +++ ArticlesApp/translation.py | 26 ++++ ArticlesApp/urls.py | 5 + ArticlesApp/urls_translate.py | 9 ++ ArticlesApp/views.py | 145 ++++++++++++++++++++++ RoutesApp/js_views.py | 2 + TWB/settings.py | 1 + TWB/urls.py | 1 + sets/admin.py | 44 +++---- templates/pages/p_article.html | 7 ++ templates/pages/p_articles.html | 9 ++ templates/pages/p_user_page.html | 7 ++ 17 files changed, 549 insertions(+), 22 deletions(-) create mode 100644 ArticlesApp/__init__.py create mode 100644 ArticlesApp/admin.py create mode 100644 ArticlesApp/migrations/0001_initial.py create mode 100644 ArticlesApp/migrations/__init__.py create mode 100644 ArticlesApp/models.py create mode 100644 ArticlesApp/tests.py create mode 100644 ArticlesApp/translation.py create mode 100644 ArticlesApp/urls.py create mode 100644 ArticlesApp/urls_translate.py create mode 100644 ArticlesApp/views.py create mode 100644 templates/pages/p_article.html create mode 100644 templates/pages/p_articles.html create mode 100644 templates/pages/p_user_page.html diff --git a/ArticlesApp/__init__.py b/ArticlesApp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ArticlesApp/admin.py b/ArticlesApp/admin.py new file mode 100644 index 0000000..074aaba --- /dev/null +++ b/ArticlesApp/admin.py @@ -0,0 +1,159 @@ +## -*- coding: utf8 -*- + +__author__ = 'SDE' +from django.contrib import admin + +from ArticlesApp.models import ArticleModel, UserPageModel +from sets.admin import * + + +# class Admin_ArticlesPageSets(Admin_BaseIconModel): +# +# fieldsets = ( +# (None, { +# 'classes': ['wide'], +# 'fields': ( +# 'name', 'url', 'description', 'picture' +# ) +# +# +# }), +# (u'Управление отображением страницы', { +# 'classes': ['wide'], +# 'fields': ( +# # ('serviceBlockStateShow'), +# # ('articlesCountInBlock'), +# # ('advicesCountInBlock'), +# ) +# }), +# +# ('SEO', { +# 'classes': ['wide', 'collapse'], +# 'fields': ('seo_title', 'seo_description','seo_keywords', 'seo_text') +# }), +# +# ) +# +# prepopulated_fields = {"url": ("name",)} +# list_display = ('name', 'url', 'seo_title', 'createDT') +# # list_editable = ('dish_price', 'allowForDelivery', 'dish_maxDiscount','dish_rating', +# # 'dish_enabled') +# # filter_horizontal = ['service_works',] +# # date_hierarchy = 'createDT' +# # list_filter = ('device_name', 'vendor',) +# list_display_links = ('name',) +# save_on_top = True +# +# def has_add_permission(self, request): +# return not ArticlesPageSets.objects.all().count() > 0 +# +# def has_delete_permission(self, request, obj=None): +# if not request.user.is_superuser: +# return False +# else: +# return True +# +# admin.site.register(ArticlesPageSets,Admin_ArticlesPageSets) + + + + +class Admin_Article(Admin_Trans_BaseModelViewPage): + + fieldsets = ( + (None, { + 'classes': ['wide'], + 'fields': (('name'), + ('url'), + # 'pub_DT', + 'picture', + # ('devices'), + ) + }), + (u'Статья', { + 'classes': ['wide'], + 'fields': ( + 'description', 'text', + ) + }), + + ('SEO', { + 'classes': ['wide', 'collapse'], + 'fields': ('seo_title', 'seo_description','seo_keywords') + }), + + ) + + prepopulated_fields = {"url": ("name",)} + list_display = ( + # 'image_thumb', + 'name', 'url', 'order', 'createDT') + list_editable = ('order',) # 'allowForDelivery', 'dish_maxDiscount','dish_rating', + # 'dish_enabled') + # filter_horizontal = ['sites'] + date_hierarchy = 'createDT' + list_filter = ('enable', 'createDT') + list_display_links = ( + 'name', + # 'image_thumb', + ) + save_on_top = True + +admin.site.register(ArticleModel, Admin_Article) + +# class Admin_ArticleSliders(admin.TabularInline): +# model = ArticleModel.SliderSets.through + + +class Admin_UserPage(Admin_Trans_BaseModelViewPage): + + fieldsets = ( + (None, { + 'classes': ['wide'], + 'fields': (('name'), + ('url'), + # 'pub_DT', + # ('devices'), + ) + }), + (u'Статья', { + 'classes': ['wide'], + 'fields': ('picture', 'description', 'text') + }), + + ('SEO', { + 'classes': ['wide', 'collapse'], + 'fields': ('seo_title', 'seo_description','seo_keywords') + }), + + ) + + prepopulated_fields = {"url": ("name",)} + list_display = ( + # 'image_thumb', + 'name', 'url', 'order', 'seo_title', 'createDT') + list_editable = ('order', ) # 'allowForDelivery', 'dish_maxDiscount','dish_rating', + # 'dish_enabled') + # filter_horizontal = ['sites'] + date_hierarchy = 'createDT' + list_filter = ('enable', 'createDT') + list_display_links = ( + 'name', + # 'image_thumb', + ) + save_on_top = True + + actions = ['create_copy'] + + + + def has_delete_permission(self, request, obj=None): + if request.user.is_superuser: + return True + + if obj and obj.url in ('for-partners', 'dealers', 'about-truenergy', 'contacts'): + return False + + return True + +admin.site.register(UserPageModel,Admin_UserPage) \ No newline at end of file diff --git a/ArticlesApp/migrations/0001_initial.py b/ArticlesApp/migrations/0001_initial.py new file mode 100644 index 0000000..bd57f1e --- /dev/null +++ b/ArticlesApp/migrations/0001_initial.py @@ -0,0 +1,103 @@ +# Generated by Django 4.2.2 on 2023-08-28 17:17 + +import ckeditor.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='ArticleModel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_ru', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_en', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_plural', models.TextField(blank=True, null=True, verbose_name='Название (множественное число)')), + ('order', models.IntegerField(blank=True, null=True, verbose_name='Очередность отображения')), + ('createDT', models.DateTimeField(auto_now_add=True, verbose_name='Дата и время создания')), + ('modifiedDT', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время последнего изменения')), + ('enable', models.BooleanField(db_index=True, default=True, verbose_name='Включено')), + ('json_data', models.JSONField(blank=True, default=dict, verbose_name='Дополнительные данные')), + ('url', models.TextField(help_text='можно изменить адрес страницы (!!! ВНИМАНИЕ !!! поисковые системы потеряют страницу и найдут лишь спустя неделю...месяц)', unique=True, verbose_name='URL привязанной страницы')), + ('title', models.TextField(blank=True, null=True, verbose_name='Заголовок')), + ('description', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('description_ru', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('description_en', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('picture', models.ImageField(blank=True, null=True, upload_to='uploads/', verbose_name='Картинка')), + ('visible', models.BooleanField(default=True, verbose_name='Отображать')), + ('background_image_left', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Левая подложка')), + ('background_image_right', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Правая подложка')), + ('seo_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_title_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_title_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_description', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_description_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_description_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_keywords', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_keywords_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_keywords_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_text', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('seo_text_ru', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('seo_text_en', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('FAQ_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок')), + ('text', ckeditor.fields.RichTextField(verbose_name='Текст')), + ('text_ru', ckeditor.fields.RichTextField(null=True, verbose_name='Текст')), + ('text_en', ckeditor.fields.RichTextField(null=True, verbose_name='Текст')), + ], + options={ + 'verbose_name': 'Статья', + 'verbose_name_plural': 'Статьи', + }, + ), + migrations.CreateModel( + name='UserPageModel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_ru', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_en', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')), + ('name_plural', models.TextField(blank=True, null=True, verbose_name='Название (множественное число)')), + ('order', models.IntegerField(blank=True, null=True, verbose_name='Очередность отображения')), + ('createDT', models.DateTimeField(auto_now_add=True, verbose_name='Дата и время создания')), + ('modifiedDT', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время последнего изменения')), + ('enable', models.BooleanField(db_index=True, default=True, verbose_name='Включено')), + ('json_data', models.JSONField(blank=True, default=dict, verbose_name='Дополнительные данные')), + ('url', models.TextField(help_text='можно изменить адрес страницы (!!! ВНИМАНИЕ !!! поисковые системы потеряют страницу и найдут лишь спустя неделю...месяц)', unique=True, verbose_name='URL привязанной страницы')), + ('title', models.TextField(blank=True, null=True, verbose_name='Заголовок')), + ('description', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('description_ru', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('description_en', ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')), + ('picture', models.ImageField(blank=True, null=True, upload_to='uploads/', verbose_name='Картинка')), + ('visible', models.BooleanField(default=True, verbose_name='Отображать')), + ('background_image_left', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Левая подложка')), + ('background_image_right', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Правая подложка')), + ('seo_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_title_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_title_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')), + ('seo_description', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_description_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_description_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')), + ('seo_keywords', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_keywords_ru', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_keywords_en', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')), + ('seo_text', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('seo_text_ru', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('seo_text_en', ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Текст SEO статьи')), + ('FAQ_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок')), + ('text', ckeditor.fields.RichTextField(verbose_name='Текст')), + ('text_ru', ckeditor.fields.RichTextField(null=True, verbose_name='Текст')), + ('text_en', ckeditor.fields.RichTextField(null=True, verbose_name='Текст')), + ], + options={ + 'verbose_name': 'Пользовательская страница', + 'verbose_name_plural': 'Пользовательские страницы', + }, + ), + ] diff --git a/ArticlesApp/migrations/__init__.py b/ArticlesApp/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ArticlesApp/models.py b/ArticlesApp/models.py new file mode 100644 index 0000000..43d21a8 --- /dev/null +++ b/ArticlesApp/models.py @@ -0,0 +1,37 @@ +# -*- coding: utf8 -*- + +__author__ = 'sync' + +from django.db import models + +from BaseModels.base_models import BaseModelViewPage, BaseModel +from ckeditor.fields import RichTextField +from django.utils.translation import gettext_lazy as _ + + +# class ArticlesPageSets(BaseModelViewPage): +# +# class Meta: +# verbose_name = 'Настройки страницы архива статей' +# verbose_name_plural = 'Настройки страницы архива статей' + + +class UserPageModel(BaseModelViewPage): + # pub_DT = models.DateTimeField(verbose_name=u'Дата и время публикации', auto_created=True) + text = RichTextField(verbose_name=u'Текст') + + class Meta: + verbose_name=u'Пользовательская страница' + verbose_name_plural =u'Пользовательские страницы' + # unique_together = ('url', 'region') + # managed=True + # app_label = u'ArticlesApp' + + +class ArticleModel(BaseModelViewPage): + # pub_DT = models.DateTimeField(verbose_name=u'Дата и время публикации', auto_created=True) + text = RichTextField(verbose_name=u'Текст') + + class Meta: + verbose_name=u'Статья' + verbose_name_plural =u'Статьи' \ No newline at end of file diff --git a/ArticlesApp/tests.py b/ArticlesApp/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/ArticlesApp/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/ArticlesApp/translation.py b/ArticlesApp/translation.py new file mode 100644 index 0000000..76a0122 --- /dev/null +++ b/ArticlesApp/translation.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +from modeltranslation.translator import translator, TranslationOptions, register +from .models import * + +@register(ArticleModel) +class Article_TranslationOptions(TranslationOptions): + + fields = ( + 'name', 'description', 'seo_title', 'seo_description', 'seo_keywords', 'seo_text', + 'text' + ) + +# translator.register(ArticleModel, Article_TranslationOptions) + + + +@register(UserPageModel) +class UserPage_TranslationOptions(TranslationOptions): + + fields = ( + 'name', 'description', 'seo_title', 'seo_description', 'seo_keywords', 'seo_text', + 'text' + ) + +# translator.register(UserPageModel, UserPage_TranslationOptions) \ No newline at end of file diff --git a/ArticlesApp/urls.py b/ArticlesApp/urls.py new file mode 100644 index 0000000..4d2588e --- /dev/null +++ b/ArticlesApp/urls.py @@ -0,0 +1,5 @@ +from django.urls import path +from .views import * + +urlpatterns = [ +] \ No newline at end of file diff --git a/ArticlesApp/urls_translate.py b/ArticlesApp/urls_translate.py new file mode 100644 index 0000000..d7313f2 --- /dev/null +++ b/ArticlesApp/urls_translate.py @@ -0,0 +1,9 @@ +from django.urls import path +from .views import * + +urlpatterns = [ + path('articles/', ArticlesPageView, name=u'articles'), + path('articles//', ArticlesPageView, name=u'articles_by_year'), + path('article//', ArticlesOnePageView, name=u'article_one'), + path('page//', UserPageView, name=u'page_one'), +] \ No newline at end of file diff --git a/ArticlesApp/views.py b/ArticlesApp/views.py new file mode 100644 index 0000000..dc7891f --- /dev/null +++ b/ArticlesApp/views.py @@ -0,0 +1,145 @@ +# -*- coding: utf8 -*- + +from .models import * + +from datetime import datetime, date +from django.http import Http404, HttpResponse +from django.template import loader + +# from django.contrib.auth.decorators import login_required +# from BaseModels.search_optimization.ld_json.ld_article_news import get_ld_article_news +# from django.contrib.sites.shortcuts import get_current_site + + + +def get_flat_pages_links_Dict(site): + + flat_pages_links = UserPageModel.objects.filter( + url__in=('about-truenergy', 'for-partners', 'contacts'), + sites=site + ).values_list('url', flat=True) + + return {'flat_pages_links': flat_pages_links} + + + +def get_article_breadcrumbs(request, art): + # print('get_article_breadcrumbs') + half_count = art.articlesCountInBlock / 2 + + art_List = ArticleModel.objects.filter(enable=True, article_DT__gte=art.article_DT).order_by( + 'article_DT')[:half_count] + artListDown = ArticleModel.objects.filter(enable=True, article_DT__lt=art.article_DT).order_by( + '-article_DT')[:art.articlesCountInBlock-len(art_List)] + if len(artListDown){{ art.name }} +
{{ art.description }}
+
{{ art.text|safe }}
+{% endblock %} \ No newline at end of file diff --git a/templates/pages/p_articles.html b/templates/pages/p_articles.html new file mode 100644 index 0000000..970c0ac --- /dev/null +++ b/templates/pages/p_articles.html @@ -0,0 +1,9 @@ +{% extends "tb_base.html" %} + +{% block content %} + {% for art in articles %} +
{{ art.name }}
+
{{ art.description }}
+
{{ art.text|safe }}
+ {% endfor %} +{% endblock %} \ No newline at end of file diff --git a/templates/pages/p_user_page.html b/templates/pages/p_user_page.html new file mode 100644 index 0000000..c2000e4 --- /dev/null +++ b/templates/pages/p_user_page.html @@ -0,0 +1,7 @@ +{% extends "tb_base.html" %} + +{% block content %} +
{{ art.name }}
+
{{ art.description }}
+
{{ art.text|safe }}
+{% endblock %} \ No newline at end of file