From cd3be918e39af291ef8713a41526ffda22caa04b Mon Sep 17 00:00:00 2001 From: SDE Date: Sun, 14 Jul 2024 17:12:05 +0300 Subject: [PATCH] 0.5.10 documentation insert video, file storage --- BaseModels/admin_utils.py | 20 ++++++++++++++++++-- DocsApp/views.py | 4 ++-- GeneralApp/admin.py | 29 +++++++++++++++++++++++++++++ GeneralApp/models.py | 12 ++++++++++++ GeneralApp/translation.py | 6 ++++++ pAerBim/settings.py | 29 ++++++++++++++++++++++------- pAerBim/urls.py | 13 +++++++++++++ 7 files changed, 102 insertions(+), 11 deletions(-) diff --git a/BaseModels/admin_utils.py b/BaseModels/admin_utils.py index dcdd965..014e480 100644 --- a/BaseModels/admin_utils.py +++ b/BaseModels/admin_utils.py @@ -124,8 +124,10 @@ def init_formfield_for_dbfield(class_model, self, db_field, request, **kwargs): formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) if db_field.name in ('lexems',): formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) - # if db_field.name == 'answer': - # formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) + if db_field.name == 'answer': + formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) + # if db_field.name in ['file']: + # formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'}) if db_field.name in ['question', 'FAQ_title']: formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'}) @@ -266,6 +268,20 @@ class Admin_BaseIconTabularModel(admin.TabularInline): class Admin_BaseIconModel(admin.ModelAdmin): + def save_model(self, request, obj, form, change): + + # ckeditor + youtube фикс + for field in form.changed_data: + if type(field) == str: + val = getattr(obj, field, None) + if val: + val = val.replace(' sandbox=""', '') + setattr(obj, field, val) + # setattr(form.instance, field, val) + # form.cleaned_data[field] = form.cleaned_data[field].replace(' sandbox=""', '') + # form.data[field] = form.data[field].replace(' sandbox=""', '') + super().save_model(request, obj, form, change) + def description_exists(self, obj): if obj.description: diff --git a/DocsApp/views.py b/DocsApp/views.py index ead9115..992ce5b 100644 --- a/DocsApp/views.py +++ b/DocsApp/views.py @@ -110,11 +110,11 @@ def DocsView(request, version=None, art_url=None): versions=None ).filter( enable=True, parent=None - ).order_by('-versions__order', 'order').first() + ).order_by('-versions__order', '-versions__name', 'order').first() if art: url = reverse( 'docs_art_page', - kwargs={'version': art.versions.order_by('order').first().url, 'art_url': art.url} + kwargs={'version': art.versions.order_by('-order').first().url, 'art_url': art.url} ) return HttpResponseRedirect(url) diff --git a/GeneralApp/admin.py b/GeneralApp/admin.py index 74e105a..579d773 100644 --- a/GeneralApp/admin.py +++ b/GeneralApp/admin.py @@ -21,6 +21,34 @@ class LogEntryAdmin(admin.ModelAdmin): admin.site.register(LogEntry, LogEntryAdmin) +class Admin_FileUnit(Admin_Trans_BaseModelViewPage): + + def formfield_for_dbfield(self, db_field, request, **kwargs): + from filebrowser.fields import FileBrowseWidget + + formfield = super(Admin_FileUnit, self).formfield_for_dbfield(db_field, request, **kwargs) + if db_field and db_field.name in ['file']: + widget_sets = formfield.widget.site + formfield.widget = FileBrowseWidget(attrs={'style': 'width: 80%'}) + formfield.widget.site = widget_sets + + return formfield + + + fieldsets = [ + (None, { + 'classes': [], + 'fields': [ + ('name',), + ('file',), + # 'image' + 'order' + ] + }) + ] +admin.site.register(FileUnit, Admin_FileUnit) + + class Admin_Inline_WidgetForBlock(SuperInlineModelAdmin, Admin_Trans_BaseIconStackedInline): @@ -40,6 +68,7 @@ class Admin_Inline_WidgetForBlock(SuperInlineModelAdmin, Admin_Trans_BaseIconSta # 'title', 'name', 'description', 'text', 'picture', + # 'image' ), 'video_url', ('bg_color', ), diff --git a/GeneralApp/models.py b/GeneralApp/models.py index a74ecb6..37bc810 100644 --- a/GeneralApp/models.py +++ b/GeneralApp/models.py @@ -1,3 +1,4 @@ +from django.core.files.storage import FileSystemStorage from django.db import models from BaseModels.base_models import * from django.utils.translation import gettext_lazy as _ @@ -8,6 +9,12 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericRelation from colorfield.fields import ColorField +from filebrowser.fields import FileBrowseField +from filebrowser.base import FileObject + +class FileUnit(BaseModel): + file = FileBrowseField(verbose_name=_('Файл'), max_length=250, directory="files/") + class StaticPage(BaseModelViewPage): promo_header = models.BooleanField(verbose_name='Промо-хэдер', default=False) @@ -120,6 +127,11 @@ class WidgetForBlock(BaseModel): validators=[validate_file_extension] ) + def image(self): + if self.picture: + return FileObject(self.picture.path) + return None + class Meta: verbose_name = _('Виджет в блоке') diff --git a/GeneralApp/translation.py b/GeneralApp/translation.py index c3501cb..e58a8a6 100644 --- a/GeneralApp/translation.py +++ b/GeneralApp/translation.py @@ -2,6 +2,12 @@ from modeltranslation.translator import translator, TranslationOptions from .models import * +class FileUnit_TranslationOptions(TranslationOptions): + fields = ( + 'name', 'file' + ) +translator.register(FileUnit, FileUnit_TranslationOptions) + class StaticPage_TranslationOptions(TranslationOptions): fields = ( 'name', 'description', 'text', 'title', 'FAQ_title', 'seo_title', 'seo_description', 'seo_text' diff --git a/pAerBim/settings.py b/pAerBim/settings.py index b07287b..01df171 100644 --- a/pAerBim/settings.py +++ b/pAerBim/settings.py @@ -29,17 +29,23 @@ DEBUG = True ALLOWED_HOSTS = ['*'] SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') -CSRF_TRUSTED_ORIGINS = ['https://aerbim.com', 'http://127.0.0.1:8019/'] - +CSRF_TRUSTED_ORIGINS = ['https://aerbim.com', 'http://127.0.0.1:8019/', 'https://www.youtube.com/'] +X_FRAME_OPTIONS = 'SAMEORIGIN' # Application definition +FILEBROWSER_SHOW_IN_DASHBOARD = False + INSTALLED_APPS = [ 'colorfield', - 'modeltranslation', - "admin_interface", 'super_inlines', + # 'grappelli', + 'filebrowser', + + "admin_interface", + 'modeltranslation', + 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -72,7 +78,7 @@ MIDDLEWARE = [ # 'AuthApp.middleware.ResponseInterceptionMiddleware', ] -X_FRAME_OPTIONS = 'SAMEORIGIN' + ROOT_URLCONF = 'pAerBim.urls' @@ -220,8 +226,12 @@ CKEDITOR_CONFIGS = { 'toolbar': 'Custom', 'forcePasteAsPlainText': True, 'allowedContent': True, + 'extraAllowedContent': 'iframe[*]', # 'disallowedContent': 'img{width,height};img[width,height]', - # 'extraPlugins': 'image2', + 'extraPlugins': ','.join([ + 'codesnippet', + # 'youtube' + ]), 'enterMode': 2, 'basicEntities' : False, @@ -250,7 +260,12 @@ CKEDITOR_CONFIGS = { '/', {'name': 'links', 'items': ['Link', 'Unlink', 'Anchor', '-', 'Blockquote' ]}, {'name': 'insert', - 'items': ['Image', 'Update', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe']}, + 'items': ['Image', 'Youtube', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe'] + }, + # { + # 'name': 'youtube', + # 'items': ['Youtube',] + # } ], } } diff --git a/pAerBim/urls.py b/pAerBim/urls.py index f13a62b..db4f8a2 100644 --- a/pAerBim/urls.py +++ b/pAerBim/urls.py @@ -3,6 +3,16 @@ from django.contrib import admin from django.urls import path, include from django.conf.urls.static import static from django.conf import settings +from filebrowser.sites import site + + +# from django.core.files.storage import DefaultStorage +# from filebrowser.sites import FileBrowserSite +# +# site = FileBrowserSite(name="filebrowser", storage=DefaultStorage()) +# customsite = FileBrowserSite(name='custom_filebrowser', storage=DefaultStorage()) +# customsite.directory = "uploads/" + urlpatterns = [ path('ckeditor/', include('ckeditor_uploader.urls')), @@ -14,6 +24,9 @@ urlpatterns = [ from django.conf.urls.i18n import i18n_patterns urlpatterns += i18n_patterns( + path('admin/filebrowser/', site.urls), + + # path('grappelli/', include('grappelli.urls')), path('admin/', admin.site.urls),