1.8.2 media for landing
This commit is contained in:
@@ -29,12 +29,31 @@ class BaseModel(models.Model):
|
|||||||
|
|
||||||
json_data = models.JSONField(verbose_name=_('Дополнительные данные'), default=dict, blank=True)
|
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):
|
def __str__(self):
|
||||||
if self.name:
|
if self.name:
|
||||||
return self.name
|
return self.name
|
||||||
else:
|
else:
|
||||||
return str(self.id)
|
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):
|
def pop_node_by_name(self, node_name):
|
||||||
if not self.json_data or not node_name in self.json_data:
|
if not self.json_data or not node_name in self.json_data:
|
||||||
return None
|
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_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')
|
FAQ_items = GenericRelation('GeneralApp.FAQitem', related_query_name='grel_%(class)s_for_faq_item')
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ from .models import *
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Admin_StaticPage(Admin_Trans_BaseModelViewPage):
|
class Admin_StaticPage(Admin_Trans_BaseModelViewPage):
|
||||||
|
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
|
|||||||
41
GeneralApp/migrations/0006_mediaitem.py
Normal file
41
GeneralApp/migrations/0006_mediaitem.py
Normal file
@@ -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': 'Медиа элементы',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -3,6 +3,26 @@ from BaseModels.base_models import BaseModelViewPage, BaseModel
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
# from ckeditor.fields import RichTextField
|
# from ckeditor.fields import RichTextField
|
||||||
from ckeditor_uploader.fields import RichTextUploadingField
|
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):
|
class StaticPage(BaseModelViewPage):
|
||||||
promo_header = models.BooleanField(verbose_name=_('Промо-хэдер'), default=False)
|
promo_header = models.BooleanField(verbose_name=_('Промо-хэдер'), default=False)
|
||||||
@@ -29,9 +49,6 @@ class Option(BaseModel):
|
|||||||
|
|
||||||
class FAQitem(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)
|
content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True)
|
||||||
object_id = models.PositiveIntegerField()
|
object_id = models.PositiveIntegerField()
|
||||||
content_object = GenericForeignKey('content_type', 'object_id')
|
content_object = GenericForeignKey('content_type', 'object_id')
|
||||||
|
|||||||
@@ -27,3 +27,9 @@ class FAQitem_TranslationOptions(TranslationOptions):
|
|||||||
)
|
)
|
||||||
translator.register(FAQitem, FAQitem_TranslationOptions)
|
translator.register(FAQitem, FAQitem_TranslationOptions)
|
||||||
|
|
||||||
|
class MediaItem_TranslationOptions(TranslationOptions):
|
||||||
|
fields = (
|
||||||
|
'name', 'comment',
|
||||||
|
)
|
||||||
|
translator.register(MediaItem, MediaItem_TranslationOptions)
|
||||||
|
|
||||||
|
|||||||
@@ -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 copy import deepcopy
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
|
||||||
class Admin_BaseModel(Admin_BaseIconModel):
|
class Admin_BaseModel(Admin_BaseIconModel):
|
||||||
@@ -86,12 +90,17 @@ class AdminTranslationBase(TranslationAdmin):
|
|||||||
'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
|
'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
|
||||||
}
|
}
|
||||||
|
|
||||||
from modeltranslation.admin import TranslationGenericStackedInline
|
from modeltranslation.admin import TranslationGenericStackedInline, TranslationGenericTabularInline
|
||||||
class AdminStacked_FAQitem(TranslationGenericStackedInline):
|
class TranslationGenericTabularInlineCustom(TranslationGenericTabularInline):
|
||||||
from GeneralApp.models import FAQitem
|
formfield_overrides = {
|
||||||
model = FAQitem
|
models.ImageField: {'widget': AdminImageWidget},
|
||||||
extra = 0
|
}
|
||||||
fields = ['order', 'question', 'answer']
|
|
||||||
|
def image_thumb(self, obj):
|
||||||
|
return get_image_thumb(self, obj)
|
||||||
|
|
||||||
|
image_thumb.short_description = _('Миниатюра')
|
||||||
|
image_thumb.allow_tags = True
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
|
|
||||||
@@ -105,6 +114,46 @@ class AdminStacked_FAQitem(TranslationGenericStackedInline):
|
|||||||
'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
|
'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):
|
class Admin_BaseModelViewPage(Admin_BaseIconModel):
|
||||||
pass
|
pass
|
||||||
# def get_fieldsets(self, request, obj=None):
|
# def get_fieldsets(self, request, obj=None):
|
||||||
@@ -129,7 +178,7 @@ class Admin_BaseModelViewPage(Admin_BaseIconModel):
|
|||||||
# else:
|
# else:
|
||||||
# return {}
|
# return {}
|
||||||
#
|
#
|
||||||
inlines = [AdminStacked_FAQitem]
|
inlines = [AdminStacked_FAQitem, AdminTabular_Mediaitem]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -133,56 +133,58 @@
|
|||||||
<div class="title">{% translate "Что о нас говорят люди" %}</div>
|
<div class="title">{% translate "Что о нас говорят люди" %}</div>
|
||||||
<div class="chatterbox__slider slick-slider">
|
<div class="chatterbox__slider slick-slider">
|
||||||
|
|
||||||
<div class="slick-slide">
|
{% for media_item in page.get_media_items %}
|
||||||
<div class="chatterbox__slide">
|
<div class="slick-slide">
|
||||||
<div class="chatterbox__vicon"></div>
|
<div class="chatterbox__slide">
|
||||||
|
<div class="chatterbox__vicon"></div>
|
||||||
|
|
||||||
<video src="https://example.com/hexlet.mp4"></video>
|
<video src="{{ MEDIA_URL }}{{ media_item.video }}"></video>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="slick-slide">
|
{% endfor %}
|
||||||
<div class="chatterbox__slide">
|
{# <div class="slick-slide">#}
|
||||||
<div class="chatterbox__vicon"></div>
|
{# <div class="chatterbox__slide">#}
|
||||||
|
{# <div class="chatterbox__vicon"></div>#}
|
||||||
<video src="https://example.com/hexlet.mp4"></video>
|
{##}
|
||||||
|
{# <video src="https://example.com/hexlet.mp4"></video>#}
|
||||||
</div>
|
{##}
|
||||||
</div>
|
{# </div>#}
|
||||||
<div class="slick-slide">
|
{# </div>#}
|
||||||
<div class="chatterbox__slide">
|
{# <div class="slick-slide">#}
|
||||||
<div class="chatterbox__vicon"></div>
|
{# <div class="chatterbox__slide">#}
|
||||||
|
{# <div class="chatterbox__vicon"></div>#}
|
||||||
<video src="https://example.com/hexlet.mp4"></video>
|
{##}
|
||||||
|
{# <video src="https://example.com/hexlet.mp4"></video>#}
|
||||||
</div>
|
{##}
|
||||||
</div>
|
{# </div>#}
|
||||||
<div class="slick-slide">
|
{# </div>#}
|
||||||
<div class="chatterbox__slide">
|
{# <div class="slick-slide">#}
|
||||||
<div class="chatterbox__vicon"></div>
|
{# <div class="chatterbox__slide">#}
|
||||||
|
{# <div class="chatterbox__vicon"></div>#}
|
||||||
|
{##}
|
||||||
</div>
|
{##}
|
||||||
</div>
|
{# </div>#}
|
||||||
<div class="slick-slide">
|
{# </div>#}
|
||||||
<div class="chatterbox__slide">
|
{# <div class="slick-slide">#}
|
||||||
<div class="chatterbox__vicon"></div>
|
{# <div class="chatterbox__slide">#}
|
||||||
|
{# <div class="chatterbox__vicon"></div>#}
|
||||||
|
{##}
|
||||||
</div>
|
{##}
|
||||||
</div>
|
{# </div>#}
|
||||||
<div class="slick-slide">
|
{# </div>#}
|
||||||
<div class="chatterbox__slide">
|
{# <div class="slick-slide">#}
|
||||||
<div class="chatterbox__vicon"></div>
|
{# <div class="chatterbox__slide">#}
|
||||||
|
{# <div class="chatterbox__vicon"></div>#}
|
||||||
|
{##}
|
||||||
</div>
|
{##}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user