From c52dbca9a19c5d63fab72d167da14e83b2fda703 Mon Sep 17 00:00:00 2001 From: SDE Date: Fri, 15 Nov 2024 15:14:50 +0300 Subject: [PATCH] 1.8.2 media for landing --- BaseModels/base_models.py | 20 +++- GeneralApp/admin.py | 2 + GeneralApp/migrations/0006_mediaitem.py | 41 ++++++++ GeneralApp/models.py | 23 +++- GeneralApp/translation.py | 6 ++ sets/admin.py | 67 ++++++++++-- templates/pages/p_customer_landing_page.html | 104 ++++++++++--------- 7 files changed, 199 insertions(+), 64 deletions(-) create mode 100644 GeneralApp/migrations/0006_mediaitem.py diff --git a/BaseModels/base_models.py b/BaseModels/base_models.py index adc86f7..db6dec5 100644 --- a/BaseModels/base_models.py +++ b/BaseModels/base_models.py @@ -29,12 +29,31 @@ class BaseModel(models.Model): json_data = models.JSONField(verbose_name=_('Дополнительные данные'), default=dict, blank=True) + media_items = GenericRelation('GeneralApp.MediaItem', related_query_name='grel_%(class)s_for_media_item') + def __str__(self): if self.name: return self.name else: return str(self.id) + def get_media_items(self, exclude_kwargs=None): + if not exclude_kwargs: + exclude_kwargs = {} + return self.media_items.exclude( + **exclude_kwargs + ).filter( + enable=True + ).order_by('order') + + def get_video_items(self): + exclude_kwargs = {'video': None} + return self.get_media_items(exclude_kwargs=exclude_kwargs) + + def get_picture_items(self): + exclude_kwargs = {'picture': None} + return self.get_media_items(exclude_kwargs=exclude_kwargs) + def pop_node_by_name(self, node_name): if not self.json_data or not node_name in self.json_data: return None @@ -108,7 +127,6 @@ class BaseModelViewPage(BaseModel): FAQ_title = models.CharField(max_length=250, verbose_name=_(u'FAQ Заголовок'), null=True, blank=True) FAQ_items = GenericRelation('GeneralApp.FAQitem', related_query_name='grel_%(class)s_for_faq_item') - class Meta: abstract = True diff --git a/GeneralApp/admin.py b/GeneralApp/admin.py index d315ceb..614dbee 100644 --- a/GeneralApp/admin.py +++ b/GeneralApp/admin.py @@ -3,6 +3,8 @@ from .models import * from django.contrib import admin from django.utils.translation import gettext as _ + + class Admin_StaticPage(Admin_Trans_BaseModelViewPage): fieldsets = [ diff --git a/GeneralApp/migrations/0006_mediaitem.py b/GeneralApp/migrations/0006_mediaitem.py new file mode 100644 index 0000000..a22296f --- /dev/null +++ b/GeneralApp/migrations/0006_mediaitem.py @@ -0,0 +1,41 @@ +# Generated by Django 4.2.2 on 2024-11-15 14:50 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('GeneralApp', '0005_option_name_en_option_name_ru_option_prefix_en_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='MediaItem', + 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='Дополнительные данные')), + ('object_id', models.PositiveIntegerField()), + ('picture', models.ImageField(blank=True, null=True, upload_to='media/', verbose_name='Фото')), + ('video', models.FileField(blank=True, null=True, upload_to='media/video/', verbose_name='Видео')), + ('comment', models.TextField(blank=True, null=True, verbose_name='Комментарий')), + ('comment_ru', models.TextField(blank=True, null=True, verbose_name='Комментарий')), + ('comment_en', models.TextField(blank=True, null=True, verbose_name='Комментарий')), + ('content_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='contenttypes.contenttype')), + ], + options={ + 'verbose_name': 'Медиа элемент', + 'verbose_name_plural': 'Медиа элементы', + }, + ), + ] diff --git a/GeneralApp/models.py b/GeneralApp/models.py index bae28a0..4ffa47c 100644 --- a/GeneralApp/models.py +++ b/GeneralApp/models.py @@ -3,6 +3,26 @@ from BaseModels.base_models import BaseModelViewPage, BaseModel from django.utils.translation import gettext_lazy as _ # from ckeditor.fields import RichTextField from ckeditor_uploader.fields import RichTextUploadingField +from django.contrib.contenttypes.models import ContentType +from django.contrib.contenttypes.fields import GenericForeignKey + + +class MediaItem(BaseModel): + + content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True) + object_id = models.PositiveIntegerField() + content_object = GenericForeignKey('content_type', 'object_id') + + picture = models.ImageField(upload_to='media/', verbose_name=_('Фото'), null=True, blank=True) + video = models.FileField(upload_to='media/video/', verbose_name=_('Видео'), null=True, blank=True) + + comment = models.TextField(verbose_name=_('Комментарий'), null=True, blank=True) + + class Meta: + verbose_name = _('Медиа элемент') + verbose_name_plural = _('Медиа элементы') + + class StaticPage(BaseModelViewPage): promo_header = models.BooleanField(verbose_name=_('Промо-хэдер'), default=False) @@ -29,9 +49,6 @@ class Option(BaseModel): class FAQitem(BaseModel): - from django.contrib.contenttypes.models import ContentType - from django.contrib.contenttypes.fields import GenericForeignKey - content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') diff --git a/GeneralApp/translation.py b/GeneralApp/translation.py index 2427687..b83f79b 100644 --- a/GeneralApp/translation.py +++ b/GeneralApp/translation.py @@ -27,3 +27,9 @@ class FAQitem_TranslationOptions(TranslationOptions): ) translator.register(FAQitem, FAQitem_TranslationOptions) +class MediaItem_TranslationOptions(TranslationOptions): + fields = ( + 'name', 'comment', + ) +translator.register(MediaItem, MediaItem_TranslationOptions) + diff --git a/sets/admin.py b/sets/admin.py index ffa7d01..494302d 100644 --- a/sets/admin.py +++ b/sets/admin.py @@ -1,6 +1,10 @@ -from BaseModels.admin_utils import Admin_GenericBaseIconStackedInline, Admin_BaseIconModel, GenericStackedInline +from BaseModels.admin_utils import ( + Admin_GenericBaseIconStackedInline, Admin_BaseIconModel, GenericStackedInline, + AdminImageWidget, get_image_thumb +) from copy import deepcopy - +from django.db import models +from django.utils.translation import gettext as _ class Admin_BaseModel(Admin_BaseIconModel): @@ -86,12 +90,17 @@ class AdminTranslationBase(TranslationAdmin): 'screen': ('modeltranslation/css/tabbed_translation_fields.css',), } -from modeltranslation.admin import TranslationGenericStackedInline -class AdminStacked_FAQitem(TranslationGenericStackedInline): - from GeneralApp.models import FAQitem - model = FAQitem - extra = 0 - fields = ['order', 'question', 'answer'] +from modeltranslation.admin import TranslationGenericStackedInline, TranslationGenericTabularInline +class TranslationGenericTabularInlineCustom(TranslationGenericTabularInline): + formfield_overrides = { + models.ImageField: {'widget': AdminImageWidget}, + } + + def image_thumb(self, obj): + return get_image_thumb(self, obj) + + image_thumb.short_description = _('Миниатюра') + image_thumb.allow_tags = True class Media: @@ -105,6 +114,46 @@ class AdminStacked_FAQitem(TranslationGenericStackedInline): 'screen': ('modeltranslation/css/tabbed_translation_fields.css',), } +class TranslationGenericStackedInlineCustom(TranslationGenericStackedInline): + formfield_overrides = { + models.ImageField: {'widget': AdminImageWidget}, + } + + def image_thumb(self, obj): + return get_image_thumb(self, obj) + + image_thumb.short_description = _('Миниатюра') + image_thumb.allow_tags = True + + class Media: + + js = ( + 'modeltranslation/js/force_jquery.js', + 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js', + 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js', + 'modeltranslation/js/tabbed_translation_fields.js', + ) + css = { + 'screen': ('modeltranslation/css/tabbed_translation_fields.css',), + } + + +class AdminStacked_FAQitem(TranslationGenericStackedInlineCustom): + from GeneralApp.models import FAQitem + model = FAQitem + extra = 0 + fields = ['order', 'question', 'answer'] + + + +class AdminTabular_Mediaitem(TranslationGenericTabularInlineCustom): + from GeneralApp.models import MediaItem + model = MediaItem + extra = 0 + fields = ['order', 'video', 'picture'] + + + class Admin_BaseModelViewPage(Admin_BaseIconModel): pass # def get_fieldsets(self, request, obj=None): @@ -129,7 +178,7 @@ class Admin_BaseModelViewPage(Admin_BaseIconModel): # else: # return {} # - inlines = [AdminStacked_FAQitem] + inlines = [AdminStacked_FAQitem, AdminTabular_Mediaitem] diff --git a/templates/pages/p_customer_landing_page.html b/templates/pages/p_customer_landing_page.html index 3c5045f..d17acdf 100644 --- a/templates/pages/p_customer_landing_page.html +++ b/templates/pages/p_customer_landing_page.html @@ -132,57 +132,59 @@
{% translate "Что о нас говорят люди" %}
- -
-
-
- - - -
-
-
-
-
- - - -
-
-
-
-
- - - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
- - - - + + {% for media_item in page.get_media_items %} +
+
+
+ + + +
+
+ {% endfor %} +{#
#} +{#
#} +{#
#} +{##} +{# #} +{##} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{##} +{# #} +{##} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{##} +{##} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{##} +{##} +{#
#} +{#
#} +{#
#} +{#
#} +{#
#} +{##} +{##} +{#
#} +{#
#} +{# #} +{# #} +{# #} +{# #} +{# #}