django-file-finder 4.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_file_finder-4.0.dev0.dist-info/METADATA +552 -0
- django_file_finder-4.0.dev0.dist-info/RECORD +425 -0
- django_file_finder-4.0.dev0.dist-info/WHEEL +5 -0
- django_file_finder-4.0.dev0.dist-info/licenses/LICENSE-filer.txt +26 -0
- django_file_finder-4.0.dev0.dist-info/licenses/LICENSE-finder.txt +39 -0
- django_file_finder-4.0.dev0.dist-info/top_level.txt +2 -0
- filer/__init__.py +16 -0
- filer/admin/__init__.py +22 -0
- filer/admin/clipboardadmin.py +186 -0
- filer/admin/fileadmin.py +262 -0
- filer/admin/folderadmin.py +1350 -0
- filer/admin/forms.py +80 -0
- filer/admin/imageadmin.py +101 -0
- filer/admin/patched/__init__.py +0 -0
- filer/admin/patched/admin_utils.py +154 -0
- filer/admin/permissionadmin.py +56 -0
- filer/admin/permissions.py +61 -0
- filer/admin/thumbnailoptionadmin.py +5 -0
- filer/admin/tools.py +149 -0
- filer/admin/views.py +89 -0
- filer/apps.py +102 -0
- filer/cache.py +91 -0
- filer/contrib/__init__.py +0 -0
- filer/contrib/clamav/__init__.py +0 -0
- filer/contrib/django_cms/__init__.py +0 -0
- filer/contrib/django_cms/cms_toolbars.py +51 -0
- filer/fields/__init__.py +0 -0
- filer/fields/file.py +137 -0
- filer/fields/folder.py +135 -0
- filer/fields/image.py +15 -0
- filer/fields/multistorage_file.py +177 -0
- filer/locale/README +2 -0
- filer/locale/ar/LC_MESSAGES/django.mo +0 -0
- filer/locale/ar/LC_MESSAGES/django.po +1278 -0
- filer/locale/bg/LC_MESSAGES/django.mo +0 -0
- filer/locale/bg/LC_MESSAGES/django.po +1257 -0
- filer/locale/bn/LC_MESSAGES/django.mo +0 -0
- filer/locale/bn/LC_MESSAGES/django.po +1237 -0
- filer/locale/ca/LC_MESSAGES/django.mo +0 -0
- filer/locale/ca/LC_MESSAGES/django.po +1294 -0
- filer/locale/cs/LC_MESSAGES/django.mo +0 -0
- filer/locale/cs/LC_MESSAGES/django.po +1298 -0
- filer/locale/de/LC_MESSAGES/django.mo +0 -0
- filer/locale/de/LC_MESSAGES/django.po +1330 -0
- filer/locale/en/LC_MESSAGES/django.mo +0 -0
- filer/locale/en/LC_MESSAGES/django.po +1313 -0
- filer/locale/es/LC_MESSAGES/django.mo +0 -0
- filer/locale/es/LC_MESSAGES/django.po +1334 -0
- filer/locale/et/LC_MESSAGES/django.mo +0 -0
- filer/locale/et/LC_MESSAGES/django.po +1260 -0
- filer/locale/eu/LC_MESSAGES/django.mo +0 -0
- filer/locale/eu/LC_MESSAGES/django.po +1274 -0
- filer/locale/fa/LC_MESSAGES/django.mo +0 -0
- filer/locale/fa/LC_MESSAGES/django.po +1239 -0
- filer/locale/fi/LC_MESSAGES/django.mo +0 -0
- filer/locale/fi/LC_MESSAGES/django.po +1305 -0
- filer/locale/fr/LC_MESSAGES/django.mo +0 -0
- filer/locale/fr/LC_MESSAGES/django.po +1339 -0
- filer/locale/gl/LC_MESSAGES/django.mo +0 -0
- filer/locale/gl/LC_MESSAGES/django.po +1261 -0
- filer/locale/he/LC_MESSAGES/django.mo +0 -0
- filer/locale/he/LC_MESSAGES/django.po +1282 -0
- filer/locale/hi/LC_MESSAGES/django.mo +0 -0
- filer/locale/hi/LC_MESSAGES/django.po +1202 -0
- filer/locale/hr/LC_MESSAGES/django.mo +0 -0
- filer/locale/hr/LC_MESSAGES/django.po +1298 -0
- filer/locale/hu/LC_MESSAGES/django.mo +0 -0
- filer/locale/hu/LC_MESSAGES/django.po +1299 -0
- filer/locale/id/LC_MESSAGES/django.mo +0 -0
- filer/locale/id/LC_MESSAGES/django.po +1239 -0
- filer/locale/it/LC_MESSAGES/django.mo +0 -0
- filer/locale/it/LC_MESSAGES/django.po +1327 -0
- filer/locale/ja/LC_MESSAGES/django.mo +0 -0
- filer/locale/ja/LC_MESSAGES/django.po +1292 -0
- filer/locale/ja_JP/LC_MESSAGES/django.mo +0 -0
- filer/locale/ja_JP/LC_MESSAGES/django.po +1252 -0
- filer/locale/lt/LC_MESSAGES/django.mo +0 -0
- filer/locale/lt/LC_MESSAGES/django.po +1313 -0
- filer/locale/lt_LT/LC_MESSAGES/django.mo +0 -0
- filer/locale/lt_LT/LC_MESSAGES/django.po +1269 -0
- filer/locale/nb/LC_MESSAGES/django.mo +0 -0
- filer/locale/nb/LC_MESSAGES/django.po +1289 -0
- filer/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
- filer/locale/nl_NL/LC_MESSAGES/django.po +1324 -0
- filer/locale/nn/LC_MESSAGES/django.mo +0 -0
- filer/locale/nn/LC_MESSAGES/django.po +1286 -0
- filer/locale/pl/LC_MESSAGES/django.mo +0 -0
- filer/locale/pl/LC_MESSAGES/django.po +1320 -0
- filer/locale/pt/LC_MESSAGES/django.mo +0 -0
- filer/locale/pt/LC_MESSAGES/django.po +1321 -0
- filer/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- filer/locale/pt_BR/LC_MESSAGES/django.po +1325 -0
- filer/locale/ru/LC_MESSAGES/django.mo +0 -0
- filer/locale/ru/LC_MESSAGES/django.po +1303 -0
- filer/locale/sk/LC_MESSAGES/django.mo +0 -0
- filer/locale/sk/LC_MESSAGES/django.po +1268 -0
- filer/locale/tr/LC_MESSAGES/django.mo +0 -0
- filer/locale/tr/LC_MESSAGES/django.po +1263 -0
- filer/locale/vi/LC_MESSAGES/django.mo +0 -0
- filer/locale/vi/LC_MESSAGES/django.po +1243 -0
- filer/locale/zh/LC_MESSAGES/django.mo +0 -0
- filer/locale/zh/LC_MESSAGES/django.po +1252 -0
- filer/locale/zh_CN/LC_MESSAGES/django.mo +0 -0
- filer/locale/zh_CN/LC_MESSAGES/django.po +1256 -0
- filer/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- filer/locale/zh_TW/LC_MESSAGES/django.po +1252 -0
- filer/management/__init__.py +0 -0
- filer/management/commands/__init__.py +0 -0
- filer/management/commands/filer_check.py +184 -0
- filer/management/commands/generate_thumbnails.py +28 -0
- filer/management/commands/import_files.py +134 -0
- filer/migrations/0001_initial.py +166 -0
- filer/migrations/0001_squashed_0016_alter_folder_index_together_remove_folder_level_and_more.py +155 -0
- filer/migrations/0002_auto_20150606_2003.py +18 -0
- filer/migrations/0003_thumbnailoption.py +27 -0
- filer/migrations/0004_auto_20160328_1434.py +17 -0
- filer/migrations/0005_auto_20160623_1425.py +29 -0
- filer/migrations/0006_auto_20160623_1627.py +18 -0
- filer/migrations/0007_auto_20161016_1055.py +16 -0
- filer/migrations/0008_auto_20171117_1313.py +19 -0
- filer/migrations/0009_auto_20171220_1635.py +17 -0
- filer/migrations/0010_auto_20180414_2058.py +17 -0
- filer/migrations/0011_auto_20190418_0137.py +31 -0
- filer/migrations/0012_file_mime_type.py +32 -0
- filer/migrations/0013_image_width_height_to_float.py +23 -0
- filer/migrations/0014_folder_permission_choices.py +28 -0
- filer/migrations/0015_alter_file_owner_alter_file_polymorphic_ctype_and_more.py +32 -0
- filer/migrations/0016_alter_folder_index_together_remove_folder_level_and_more.py +33 -0
- filer/migrations/0017_image__transparent.py +18 -0
- filer/migrations/0018_alter_file_options.py +17 -0
- filer/migrations/__init__.py +0 -0
- filer/models/__init__.py +6 -0
- filer/models/abstract.py +301 -0
- filer/models/clipboardmodels.py +57 -0
- filer/models/filemodels.py +444 -0
- filer/models/foldermodels.py +403 -0
- filer/models/imagemodels.py +66 -0
- filer/models/mixins.py +30 -0
- filer/models/thumbnailoptionmodels.py +61 -0
- filer/models/tools.py +37 -0
- filer/models/virtualitems.py +111 -0
- filer/server/__init__.py +0 -0
- filer/server/backends/__init__.py +0 -0
- filer/server/backends/base.py +45 -0
- filer/server/backends/default.py +34 -0
- filer/server/backends/nginx.py +27 -0
- filer/server/backends/xsendfile.py +17 -0
- filer/server/main_server_urls.py +8 -0
- filer/server/thumbnails_server_urls.py +8 -0
- filer/server/urls.py +12 -0
- filer/server/views.py +57 -0
- filer/settings.py +337 -0
- filer/static/filer/css/admin_filer.cms.icons.css +1 -0
- filer/static/filer/css/admin_filer.css +3 -0
- filer/static/filer/css/admin_filer.fa.icons.css +4 -0
- filer/static/filer/css/admin_folderpermissions.css +6 -0
- filer/static/filer/css/maps/admin_filer.cms.icons.css.map +1 -0
- filer/static/filer/css/maps/admin_filer.css.map +1 -0
- filer/static/filer/css/maps/admin_filer.fa.icons.css.map +1 -0
- filer/static/filer/fonts/FontAwesome.otf +0 -0
- filer/static/filer/fonts/django-filer-iconfont.eot +0 -0
- filer/static/filer/fonts/django-filer-iconfont.svg +51 -0
- filer/static/filer/fonts/django-filer-iconfont.ttf +0 -0
- filer/static/filer/fonts/django-filer-iconfont.woff +0 -0
- filer/static/filer/fonts/django-filer-iconfont.woff2 +0 -0
- filer/static/filer/fonts/fontawesome-webfont.eot +0 -0
- filer/static/filer/fonts/fontawesome-webfont.svg +640 -0
- filer/static/filer/fonts/fontawesome-webfont.ttf +0 -0
- filer/static/filer/fonts/fontawesome-webfont.woff +0 -0
- filer/static/filer/fonts/fontawesome-webfont.woff2 +0 -0
- filer/static/filer/fonts/src/arrow-down.svg +41 -0
- filer/static/filer/fonts/src/caret-down.svg +3 -0
- filer/static/filer/fonts/src/chevron-right.svg +3 -0
- filer/static/filer/fonts/src/download.svg +4 -0
- filer/static/filer/fonts/src/expand.svg +3 -0
- filer/static/filer/fonts/src/link.svg +4 -0
- filer/static/filer/fonts/src/move-to-folder.svg +3 -0
- filer/static/filer/fonts/src/picture.svg +4 -0
- filer/static/filer/fonts/src/remove-selection.svg +3 -0
- filer/static/filer/fonts/src/select.svg +3 -0
- filer/static/filer/fonts/src/th-large.svg +3 -0
- filer/static/filer/fonts/src/th-list.svg +5 -0
- filer/static/filer/fonts/src/upload.svg +3 -0
- filer/static/filer/icons/cloud-up.svg +8 -0
- filer/static/filer/icons/file-audio.svg +11 -0
- filer/static/filer/icons/file-empty.svg +8 -0
- filer/static/filer/icons/file-font.svg +11 -0
- filer/static/filer/icons/file-missing.svg +84 -0
- filer/static/filer/icons/file-pdf.svg +11 -0
- filer/static/filer/icons/file-picture.svg +11 -0
- filer/static/filer/icons/file-spreadsheet.svg +10 -0
- filer/static/filer/icons/file-unknown.svg +69 -0
- filer/static/filer/icons/file-video.svg +8 -0
- filer/static/filer/icons/file-zip.svg +14 -0
- filer/static/filer/icons/folder-dropdown.svg +85 -0
- filer/static/filer/icons/folder-root.svg +10 -0
- filer/static/filer/icons/folder-unfiled.svg +77 -0
- filer/static/filer/icons/folder.svg +9 -0
- filer/static/filer/img/button-bg.gif +0 -0
- filer/static/filer/img/close.gif +0 -0
- filer/static/filer/img/icon_changelink.gif +0 -0
- filer/static/filer/img/icon_deletelink.gif +0 -0
- filer/static/filer/img/loading_animation.gif +0 -0
- filer/static/filer/img/nav-bg.gif +0 -0
- filer/static/filer/img/select_item-hover.gif +0 -0
- filer/static/filer/img/select_item.gif +0 -0
- filer/static/filer/img/upload_button.png +0 -0
- filer/static/filer/js/addons/copy-move-files.js +32 -0
- filer/static/filer/js/addons/csrf.js +24 -0
- filer/static/filer/js/addons/dropdown-menu.js +249 -0
- filer/static/filer/js/addons/dropzone.init.js +342 -0
- filer/static/filer/js/addons/filer_popup_response.js +22 -0
- filer/static/filer/js/addons/focal-point.js +274 -0
- filer/static/filer/js/addons/popup_handling.js +137 -0
- filer/static/filer/js/addons/table-dropzone.js +289 -0
- filer/static/filer/js/addons/toggler.js +82 -0
- filer/static/filer/js/addons/tooltip.js +40 -0
- filer/static/filer/js/addons/upload-button.js +245 -0
- filer/static/filer/js/addons/widget.js +57 -0
- filer/static/filer/js/base.js +417 -0
- filer/static/filer/js/dist/LICENSES.txt +57 -0
- filer/static/filer/js/dist/admin-file-widget.bundle.js +1 -0
- filer/static/filer/js/dist/filer-base.bundle.js +13 -0
- filer/static/filer/js/widgets/admin-file-widget.js +30 -0
- filer/static/filer/js/widgets/admin-folder-widget.js +64 -0
- filer/storage.py +20 -0
- filer/templates/admin/filer/actions.html +16 -0
- filer/templates/admin/filer/base_site.html +17 -0
- filer/templates/admin/filer/breadcrumbs.html +44 -0
- filer/templates/admin/filer/change_form.html +36 -0
- filer/templates/admin/filer/delete_confirmation.html +10 -0
- filer/templates/admin/filer/delete_selected_files_confirmation.html +51 -0
- filer/templates/admin/filer/dismiss_popup.html +8 -0
- filer/templates/admin/filer/file/change_form.html +23 -0
- filer/templates/admin/filer/file/popup_response.html +10 -0
- filer/templates/admin/filer/folder/change_form.html +54 -0
- filer/templates/admin/filer/folder/choose_copy_destination.html +76 -0
- filer/templates/admin/filer/folder/choose_images_resize_options.html +45 -0
- filer/templates/admin/filer/folder/choose_move_destination.html +72 -0
- filer/templates/admin/filer/folder/choose_rename_format.html +65 -0
- filer/templates/admin/filer/folder/directory_listing.html +226 -0
- filer/templates/admin/filer/folder/directory_table_list.html +255 -0
- filer/templates/admin/filer/folder/directory_thumbnail_list.html +227 -0
- filer/templates/admin/filer/folder/legacy_listing.html +226 -0
- filer/templates/admin/filer/folder/list_type_switcher.html +1 -0
- filer/templates/admin/filer/folder/listing_breadcrumbs.html +64 -0
- filer/templates/admin/filer/folder/new_folder_form.html +38 -0
- filer/templates/admin/filer/image/change_form.html +22 -0
- filer/templates/admin/filer/image/expand.html +28 -0
- filer/templates/admin/filer/templatetags/file_icon.html +38 -0
- filer/templates/admin/filer/tools/clipboard/clipboard.html +54 -0
- filer/templates/admin/filer/tools/clipboard/clipboard_item_rows.html +19 -0
- filer/templates/admin/filer/tools/detail_info.html +55 -0
- filer/templates/admin/filer/tools/search_form.html +9 -0
- filer/templates/admin/filer/widgets/admin_file.html +64 -0
- filer/templates/admin/filer/widgets/admin_folder.html +24 -0
- filer/templatetags/__init__.py +0 -0
- filer/templatetags/filer_admin_tags.py +263 -0
- filer/templatetags/filer_image_tags.py +139 -0
- filer/templatetags/filer_tags.py +106 -0
- filer/thumbnail_processors.py +161 -0
- filer/urls.py +13 -0
- filer/utils/__init__.py +0 -0
- filer/utils/compatibility.py +33 -0
- filer/utils/filer_easy_thumbnails.py +204 -0
- filer/utils/files.py +174 -0
- filer/utils/generate_filename.py +33 -0
- filer/utils/loader.py +56 -0
- filer/utils/model_label.py +17 -0
- filer/utils/pil_exif.py +29 -0
- filer/utils/recursive_dictionary.py +79 -0
- filer/utils/svg.py +431 -0
- filer/utils/zip.py +24 -0
- filer/validation.py +205 -0
- filer/views.py +14 -0
- finder/__init__.py +1 -0
- finder/admin/__init__.py +4 -0
- finder/admin/ambit.py +146 -0
- finder/admin/file.py +138 -0
- finder/admin/folder.py +582 -0
- finder/admin/inode.py +330 -0
- finder/apps.py +19 -0
- finder/browser/__init__.py +0 -0
- finder/browser/urls.py +69 -0
- finder/browser/views.py +388 -0
- finder/checks.py +60 -0
- finder/contrib/__init__.py +0 -0
- finder/contrib/archive/__init__.py +0 -0
- finder/contrib/archive/admin.py +183 -0
- finder/contrib/archive/models.py +13 -0
- finder/contrib/audio/__init__.py +0 -0
- finder/contrib/audio/admin.py +17 -0
- finder/contrib/audio/forms.py +23 -0
- finder/contrib/audio/models.py +63 -0
- finder/contrib/common/__init__.py +0 -0
- finder/contrib/common/admin.py +33 -0
- finder/contrib/common/models.py +110 -0
- finder/contrib/image/__init__.py +0 -0
- finder/contrib/image/admin.py +44 -0
- finder/contrib/image/forms.py +40 -0
- finder/contrib/image/models.py +188 -0
- finder/contrib/image/pil/__init__.py +0 -0
- finder/contrib/image/pil/admin.py +29 -0
- finder/contrib/image/pil/forms.py +4 -0
- finder/contrib/image/pil/models.py +100 -0
- finder/contrib/image/svg/__init__.py +0 -0
- finder/contrib/image/svg/admin.py +7 -0
- finder/contrib/image/svg/forms.py +4 -0
- finder/contrib/image/svg/models.py +57 -0
- finder/contrib/image/svg/validators.py +71 -0
- finder/contrib/video/__init__.py +0 -0
- finder/contrib/video/admin.py +17 -0
- finder/contrib/video/forms.py +21 -0
- finder/contrib/video/models.py +95 -0
- finder/exceptions.py +13 -0
- finder/forms/__init__.py +0 -0
- finder/forms/fields.py +37 -0
- finder/forms/file.py +35 -0
- finder/forms/widgets.py +90 -0
- finder/locale/ar/LC_MESSAGES/django.mo +0 -0
- finder/locale/ar/LC_MESSAGES/django.po +406 -0
- finder/locale/bn/LC_MESSAGES/django.mo +0 -0
- finder/locale/bn/LC_MESSAGES/django.po +395 -0
- finder/locale/de/LC_MESSAGES/django.mo +0 -0
- finder/locale/de/LC_MESSAGES/django.po +416 -0
- finder/locale/en/LC_MESSAGES/django.mo +0 -0
- finder/locale/en/LC_MESSAGES/django.po +394 -0
- finder/locale/es/LC_MESSAGES/django.mo +0 -0
- finder/locale/es/LC_MESSAGES/django.po +408 -0
- finder/locale/fi/LC_MESSAGES/django.mo +0 -0
- finder/locale/fi/LC_MESSAGES/django.po +399 -0
- finder/locale/fr/LC_MESSAGES/django.mo +0 -0
- finder/locale/fr/LC_MESSAGES/django.po +416 -0
- finder/locale/hi/LC_MESSAGES/django.mo +0 -0
- finder/locale/hi/LC_MESSAGES/django.po +400 -0
- finder/locale/id/LC_MESSAGES/django.mo +0 -0
- finder/locale/id/LC_MESSAGES/django.po +405 -0
- finder/locale/ko/LC_MESSAGES/django.mo +0 -0
- finder/locale/ko/LC_MESSAGES/django.po +391 -0
- finder/locale/nl/LC_MESSAGES/django.mo +0 -0
- finder/locale/nl/LC_MESSAGES/django.po +410 -0
- finder/locale/ru/LC_MESSAGES/django.mo +0 -0
- finder/locale/ru/LC_MESSAGES/django.po +400 -0
- finder/locale/sq/LC_MESSAGES/django.mo +0 -0
- finder/locale/sq/LC_MESSAGES/django.po +399 -0
- finder/locale/vi/LC_MESSAGES/django.mo +0 -0
- finder/locale/vi/LC_MESSAGES/django.po +394 -0
- finder/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- finder/locale/zh_Hans/LC_MESSAGES/django.po +391 -0
- finder/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
- finder/locale/zh_Hant/LC_MESSAGES/django.po +391 -0
- finder/lookups.py +73 -0
- finder/management/__init__.py +0 -0
- finder/management/commands/__init__.py +0 -0
- finder/management/commands/filer_to_finder.py +134 -0
- finder/management/commands/finder.py +241 -0
- finder/migrations/0001_initial.py +394 -0
- finder/migrations/__init__.py +0 -0
- finder/models/__init__.py +4 -0
- finder/models/ambit.py +62 -0
- finder/models/fields.py +111 -0
- finder/models/file.py +296 -0
- finder/models/filetag.py +32 -0
- finder/models/folder.py +480 -0
- finder/models/inode.py +412 -0
- finder/models/permission.py +279 -0
- finder/settings.py +63 -0
- finder/static/finder/css/finder-admin.css +1 -0
- finder/static/finder/css/finder-browser.css +1 -0
- finder/static/finder/css/finder-select.css +1 -0
- finder/static/finder/icons/file-audio.svg +11 -0
- finder/static/finder/icons/file-code.svg +13 -0
- finder/static/finder/icons/file-pdf.svg +11 -0
- finder/static/finder/icons/file-picture.svg +11 -0
- finder/static/finder/icons/file-spreadsheet.svg +10 -0
- finder/static/finder/icons/file-text.svg +9 -0
- finder/static/finder/icons/file-unknown.svg +69 -0
- finder/static/finder/icons/file-video.svg +8 -0
- finder/static/finder/icons/file-word.svg +15 -0
- finder/static/finder/icons/file-zip.svg +14 -0
- finder/static/finder/icons/folder-open.svg +8 -0
- finder/static/finder/icons/folder.svg +9 -0
- finder/static/finder/js/LICENSES.txt +713 -0
- finder/static/finder/js/Preview-O4JBFL6E.js +149 -0
- finder/static/finder/js/chunk-2N4KYP4W.js +68 -0
- finder/static/finder/js/chunk-325KA3A4.js +20 -0
- finder/static/finder/js/chunk-47NEGY7S.js +104 -0
- finder/static/finder/js/chunk-CP535C4P.js +97 -0
- finder/static/finder/js/chunk-D2Y5GODP.js +14 -0
- finder/static/finder/js/chunk-DT5UEGHU.js +4105 -0
- finder/static/finder/js/chunk-HEYVBD4V.js +99 -0
- finder/static/finder/js/chunk-IBFP2HMT.js +72 -0
- finder/static/finder/js/chunk-KHF6WAKM.js +4129 -0
- finder/static/finder/js/chunk-KNWCMEYY.js +179 -0
- finder/static/finder/js/chunk-LNYHHDVL.js +411 -0
- finder/static/finder/js/chunk-OTTSRNB4.js +97 -0
- finder/static/finder/js/chunk-QMKMWYMD.js +804 -0
- finder/static/finder/js/chunk-UQPTPEX7.js +1054 -0
- finder/static/finder/js/chunk-VG6P5O3O.js +25869 -0
- finder/static/finder/js/chunk-YJPL3M4U.js +113 -0
- finder/static/finder/js/components/browser/Image.js +43 -0
- finder/static/finder/js/components/editor/Archive.js +47 -0
- finder/static/finder/js/components/editor/Audio.js +2606 -0
- finder/static/finder/js/components/editor/Common.js +19 -0
- finder/static/finder/js/components/editor/Image.js +169 -0
- finder/static/finder/js/components/editor/Video.js +1817 -0
- finder/static/finder/js/components/folderitem/Audio.js +35 -0
- finder/static/finder/js/components/folderitem/Video.js +64 -0
- finder/static/finder/js/components/menuextension/Archive.js +52 -0
- finder/static/finder/js/file-admin.js +87 -0
- finder/static/finder/js/finder-select.js +1276 -0
- finder/static/finder/js/folder-admin.js +1963 -0
- finder/storages.py +198 -0
- finder/templates/finder/admin/base_site.html +27 -0
- finder/templates/finder/admin/base_site.legacy.html +27 -0
- finder/templates/finder/admin/change_file_form.html +49 -0
- finder/templates/finder/admin/change_folder_form.html +5 -0
- finder/templates/finder/forms/div.html +15 -0
- finder/templates/finder/widgets/finder_file_select.html +1 -0
- finder/templates/finder/widgets/finder_folder_select.html +1 -0
- finder/templatetags/__init__.py +0 -0
- finder/templatetags/finder_tags.py +16 -0
- finder/utils/__init__.py +0 -0
- finder/utils/svg.py +324 -0
- finder/validators.py +149 -0
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-file-finder
|
|
3
|
+
Version: 4.0.dev0
|
|
4
|
+
Summary: A media asset management application for Django.
|
|
5
|
+
Author-email: Jacob Rief <jacob.rief@gmail.com>
|
|
6
|
+
Maintainer-email: Django CMS Association and contributors <info@django-cms.org>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/django-cms/django-filer
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Framework :: Django
|
|
19
|
+
Classifier: Framework :: Django :: 5.2
|
|
20
|
+
Classifier: Framework :: Django :: 6.0
|
|
21
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
23
|
+
Classifier: Topic :: Software Development
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE-filer.txt
|
|
28
|
+
License-File: LICENSE-finder.txt
|
|
29
|
+
Requires-Dist: django>=5.2
|
|
30
|
+
Provides-Extra: cte
|
|
31
|
+
Requires-Dist: django-cte; extra == "cte"
|
|
32
|
+
Provides-Extra: heif
|
|
33
|
+
Requires-Dist: pillow-heif; extra == "heif"
|
|
34
|
+
Provides-Extra: audio
|
|
35
|
+
Requires-Dist: ffmpeg-python; extra == "audio"
|
|
36
|
+
Requires-Dist: django-entangled; extra == "audio"
|
|
37
|
+
Provides-Extra: image
|
|
38
|
+
Requires-Dist: Pillow; extra == "image"
|
|
39
|
+
Requires-Dist: django-entangled; extra == "image"
|
|
40
|
+
Provides-Extra: svg
|
|
41
|
+
Requires-Dist: django-entangled; extra == "svg"
|
|
42
|
+
Requires-Dist: py-svg-hush; extra == "svg"
|
|
43
|
+
Provides-Extra: video
|
|
44
|
+
Requires-Dist: ffmpeg-python; extra == "video"
|
|
45
|
+
Requires-Dist: django-entangled; extra == "video"
|
|
46
|
+
Provides-Extra: s3
|
|
47
|
+
Requires-Dist: django-storages[s3]; extra == "s3"
|
|
48
|
+
Provides-Extra: e2e
|
|
49
|
+
Requires-Dist: playwright; extra == "e2e"
|
|
50
|
+
Requires-Dist: pytest; extra == "e2e"
|
|
51
|
+
Requires-Dist: pytest-django; extra == "e2e"
|
|
52
|
+
Requires-Dist: Pillow; extra == "e2e"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# Django-Filer ("Finder" branch)
|
|
56
|
+
|
|
57
|
+
The "Finder" branch of django-filer is a complete rewrite of the original **django-filer** project.
|
|
58
|
+
|
|
59
|
+
A rewrite was necessary because the original codebase was not maintainable anymore. Please read this
|
|
60
|
+
[discussion](https://github.com/django-cms/django-filer/discussions/1348) for details. Apart from the maintainability issues, using the File and Folder
|
|
61
|
+
models was not possible in a multi-tenant environment. Extending the file model with a more
|
|
62
|
+
specialized implementation was possible in theory, but so complicated that apart from the
|
|
63
|
+
`ImageModel` no other implementations ever have been created.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Less third-party dependencies
|
|
67
|
+
|
|
68
|
+
The "Finder" branch of **django-filer** has less third-party dependencies. It does not depend on
|
|
69
|
+
[django-polymorphic](https://django-polymorphic.readthedocs.io/en/stable/),
|
|
70
|
+
[django-mptt](https://django-mptt.readthedocs.io/en/latest/) and
|
|
71
|
+
[easy-thumbnails](https://easy-thumbnails.readthedocs.io/en/latest/) anymore.
|
|
72
|
+
|
|
73
|
+
For large datasets [django-cte](https://github.com/dimagi/django-cte) is reccomended, in order to improve the speed
|
|
74
|
+
of tree travesals, which is important while searching.
|
|
75
|
+
|
|
76
|
+
Since each `FileModel` contains a `JSONField` to store arbitrary data, [django-entangled](https://github.com/jrief/django-entangled)
|
|
77
|
+
is reccomended, in order to give users the opportunity to edit the contents of that field.
|
|
78
|
+
|
|
79
|
+
The client part of the new admin user interface has no runtime dependencies. It is compiled into two
|
|
80
|
+
JavaScript files, which are included by the corresponding admin views. One of them is used for the
|
|
81
|
+
django-admin interface, the other one for the frontend. The frontend part is also used for the new
|
|
82
|
+
file selection widget.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## Extensibility
|
|
86
|
+
|
|
87
|
+
The "Finder" branch of django-filer is designed to be extensible for every MIME-type one desires.
|
|
88
|
+
Therefore, those extensions might need their own dependencies in order to extract or visualize a
|
|
89
|
+
certain type of file. A minimal installation can be configured to only distinguish between files
|
|
90
|
+
and folders.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## Multiple Ambits to hold Folder Roots
|
|
94
|
+
|
|
95
|
+
The "Finder" branch of **django-filer** allows multiple ambits, each able to hold multiple root
|
|
96
|
+
folders. Such an ambit must be created using the management command `manage.py finder add-ambit …`.
|
|
97
|
+
Each ambit has a slug and a name. The slug is used in the URL to access that ambit, while the name
|
|
98
|
+
is used for display purposes. All ambits are displayed in the left sidebar of the Django admin. For
|
|
99
|
+
each ambit, a different Django storage can be configured.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
## New Model Features
|
|
103
|
+
|
|
104
|
+
The "Finder" branch introduces a new model named `InodeModel`. This is the base class for all other
|
|
105
|
+
models, such as the `FileModel`, the `FolderModel` and all other specialized implementations. By
|
|
106
|
+
using a UUID instead of a numerical primary key, it is possible to use different database tables
|
|
107
|
+
while preserving the possibility to perform queries across all tables. This allows us to register
|
|
108
|
+
models inheriting from the `AbstractFileModel` without the need of **django-polymorphic**, and thus
|
|
109
|
+
a join between two or more tables for each query.
|
|
110
|
+
|
|
111
|
+
Multiple ambits are allowed, each containg one root folder, one trash folder per user and a list of
|
|
112
|
+
allowed tags. Each ambit must explictly be created using a management command. All ambits are
|
|
113
|
+
displayed in the left sidebar of the Django admin. For each ambit, a different Django storage can be
|
|
114
|
+
configured. It also is possible to restrict an ambit to a Site and/or to an AdminSite.
|
|
115
|
+
|
|
116
|
+
The Admin interface has also been completely rewritten. For instance, there is no more list view for
|
|
117
|
+
the `FolderModel` and the `FileModel` (or any specialized implementation). Instead, there are only
|
|
118
|
+
details views for each of those models. This is much nearer to what a user would expect from a file
|
|
119
|
+
system. Therefore, if a user wants to access the list view of a folder, he is redirected immediately
|
|
120
|
+
to the detail view of the root folder of the given ambit. From there, he can traverse the folder
|
|
121
|
+
tree in the same manner he's used to from his operating system.
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## New User Interface
|
|
125
|
+
|
|
126
|
+
The user interface has also been completely rewritten. It offers drag and drop functionality for
|
|
127
|
+
moving files and folders. It now is possible to select multiple files and folders at once by a
|
|
128
|
+
rectangular selection with the mouse.
|
|
129
|
+
Double-clicking on a folder opens it, by loading the detail view for that `FolderModel`. Selected
|
|
130
|
+
files or folders can be dragged into a target folder. They can also be cutted or copied to a
|
|
131
|
+
clipboard and pasted into another folder.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
### Trash Folder
|
|
135
|
+
|
|
136
|
+
Each user now has its *own private trash* folder. Whenever he deletes a file or folder, it is moved
|
|
137
|
+
to that trash folder. From there, he can restore the file or folder, or delete it permanently. The
|
|
138
|
+
trash folder can be emptied automatically after a given time period.
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
## Permission System
|
|
142
|
+
|
|
143
|
+
The permission system of **django-filer** is using the concept of Access Control Lists (ACLs)
|
|
144
|
+
similar to Posix or NTFS ACLs. This allows granting fine-grained permissions to everybody,
|
|
145
|
+
individual users and/or groups for each file and folder.
|
|
146
|
+
|
|
147
|
+
Permissions are controlled through the model named `AccessControlEntry`. This model has a foreign
|
|
148
|
+
key onto `InodeModel` and a so-called "principal". A principal is either a user, a group or for
|
|
149
|
+
everyone. They are mutually exclusive and implemented as a nullable foreign key onto `User`, or a
|
|
150
|
+
foreign key onto `Group`. Either of them can be set, but not both. If neither is set, the permission
|
|
151
|
+
is considered for everyone.
|
|
152
|
+
|
|
153
|
+
By using a separate model `AccessControlEntry`, **django-filer** can now compute the permissions
|
|
154
|
+
using just one database (sub-)query while filtering all inodes. Until version 3, the permissions had
|
|
155
|
+
to be computed traversing all ancestors starting from the current folder up to the root of the
|
|
156
|
+
folder tree. This was a time-consuming operation and made **django-filer** slow for large datasets.
|
|
157
|
+
|
|
158
|
+
Each `AccessControlEntry` has a bitmap field used to represent:
|
|
159
|
+
* `write` set for a folder: Allows the user to upload a file, to change the name of that folder,
|
|
160
|
+
to reorder files in that folder, to move files out of that filer.
|
|
161
|
+
* `write` set for a file: Allows the user to replace a file, to edit the file's meta-data, and to
|
|
162
|
+
move the file to another folder, if the source and target folders have write permissions.
|
|
163
|
+
* `read` set for a folder: Allows the user to open that folder and view its content.
|
|
164
|
+
* `read` set for a file: Allows the user to view a thumbnail of that file inside its containing
|
|
165
|
+
folder and use that file, including copying.
|
|
166
|
+
* `admin`: Allows the user to change the permissions of that folder or file.
|
|
167
|
+
* A generic foreign key pointing onto the `InodeModel`. This creates a one-to-many relation between
|
|
168
|
+
different file types and folders on one side and the access control list on the other.
|
|
169
|
+
|
|
170
|
+
In addition to `AccessControlEntry` the permission system also provides a model named
|
|
171
|
+
`DefaultAccessControlEntry`. This acts as a template for newely files or folders created inside, or
|
|
172
|
+
move to another folder.
|
|
173
|
+
The `DefaultAccessControlEntry` is implemented as a separate model with a foreign key onto the
|
|
174
|
+
`FolderModel`, because it is not possible to use the `AccessControlEntry` for both purposes, since
|
|
175
|
+
the default permissions must be inherited by all children of a folder, while the regular
|
|
176
|
+
permissions only apply to the file or folder they are attached to.
|
|
177
|
+
|
|
178
|
+
A foreign key onto the folder model to set a permission template. Read below for details.
|
|
179
|
+
|
|
180
|
+
If a folder has `write` but no `read` permission, the user can upload files into that folder, but
|
|
181
|
+
doesn't see files from other users. This is named the "Dropbox" functionality.
|
|
182
|
+
|
|
183
|
+
Each file and folder has a foreign key named `owner`, pointing onto the `User` model. The owner of a
|
|
184
|
+
file or folder can change its permissions if he has the global permission to do so. When creating a
|
|
185
|
+
new file or folder, the currently loggedin user is set as the owner of that file or folder.
|
|
186
|
+
|
|
187
|
+
Only a superuser and the owner of a file or folder can change its permissions. The superuser can
|
|
188
|
+
change the permissions of any file or folder. Staff users can change the permissions only of files
|
|
189
|
+
they own themselves.
|
|
190
|
+
|
|
191
|
+
Only a superuser can change the owner of a file or folder.
|
|
192
|
+
|
|
193
|
+
In addition to the file and folder permissions, each folder requires a template of permissions on how to
|
|
194
|
+
inherit them to files and folders created as children of that specific folder. This can be achieved with
|
|
195
|
+
a separate foreign key in model `AccessControlEntry` pointing onto the `FolderModel`.
|
|
196
|
+
|
|
197
|
+
Microsoft gives a good explanation on the implementation of
|
|
198
|
+
[ACLs in their Data-Lake implementation](https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control).
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
### Alternative Views
|
|
202
|
+
|
|
203
|
+
The user interface offers four alternative views for the folder tree.
|
|
204
|
+
|
|
205
|
+
**Tiles** is a "flat" view, which shows all files and folders as a bunch of tiles.
|
|
206
|
+
|
|
207
|
+
**Mosaic** is very similar to the "Tiles" view, but shows a much smaller version of those file,
|
|
208
|
+
folder and image icons.
|
|
209
|
+
|
|
210
|
+
**List** is a view with detailed information about every file or folder. Here every item requires a
|
|
211
|
+
separate row.
|
|
212
|
+
|
|
213
|
+
**Column** is a view which shows columns for the currently selected folder and each of its
|
|
214
|
+
ancestors. This allows to easily move files between those folders.
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
### Multiple Favrourite Folders
|
|
218
|
+
|
|
219
|
+
Each user can have multiple favourite folders. This allows him to quickly access those folders from
|
|
220
|
+
the navigation bar. It is also possible to drag a file from the current view into one of the tabs
|
|
221
|
+
for of the favorite folders.
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
### Implementation Details
|
|
225
|
+
|
|
226
|
+
The new user interface is based on the [React](https://reactjs.org/) framework with the
|
|
227
|
+
[DnD-Kit](https://docs.dndkit.com/) as its main additional dependency.
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
## Installation
|
|
231
|
+
|
|
232
|
+
The new version of **django-filer** is not yet available on PyPI. Therefore, you have to install it
|
|
233
|
+
from GitHub:
|
|
234
|
+
|
|
235
|
+
```shell
|
|
236
|
+
git clone https://github.com/django-cms/django-filer.git
|
|
237
|
+
cd django-filer
|
|
238
|
+
git switch finder
|
|
239
|
+
pip install --no-deps -e .
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The new version of **django-filer** requires Django-5.2 or later.
|
|
243
|
+
|
|
244
|
+
The new version of **django-filer** currently has only been tested with SQLite and Postgres, but
|
|
245
|
+
should also work on MariaDB and MySQL.
|
|
246
|
+
|
|
247
|
+
In `settings.py` of your project, add these extra dependencies or those you really need:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
INSTALLED_APPS = [
|
|
251
|
+
...
|
|
252
|
+
'finder',
|
|
253
|
+
'finder.contrib.archive', # supports zip, tar, tar.gz, tar.bz2, tar.xz
|
|
254
|
+
'finder.contrib.audio', # supports mp3, ogg, flac, wav
|
|
255
|
+
'finder.contrib.common', # supports PDF, spreadsheets
|
|
256
|
+
'finder.contrib.image.pil', # supports bmp, gif, jpeg, png, tiff
|
|
257
|
+
'finder.contrib.image.svg', # supports svg
|
|
258
|
+
'finder.contrib.video', # supports mp4, webm, ogv
|
|
259
|
+
...
|
|
260
|
+
]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
If you use:
|
|
264
|
+
* `finder.contrib.audio` or `finder.contrib.video`, assure that `ffmpeg-python` is installed.
|
|
265
|
+
* `finder.contrib.image.pil`, assure that `Pillow` is installed.
|
|
266
|
+
* `finder.contrib.image.svg` needs no extra dependency; it reads an SVG's size from the
|
|
267
|
+
document and thumbnails it by rewriting the root element. Documents that state their
|
|
268
|
+
size only in relative units (`width="100%"` without a `viewBox`) cannot be measured
|
|
269
|
+
that way and are shown with a generic icon.
|
|
270
|
+
* Postgres as a database, install `psycopg2` or `psycopg2-binary` if available for your platform.
|
|
271
|
+
|
|
272
|
+
Each root folder requires two storage backends. One for the public files and one for their
|
|
273
|
+
thumbnails and/or samples. Add these storage backends to the `STORAGES` setting in your
|
|
274
|
+
`settings.py`:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
STORAGES = {
|
|
278
|
+
'default': {
|
|
279
|
+
'BACKEND': 'django.core.files.storage.FileSystemStorage',
|
|
280
|
+
},
|
|
281
|
+
'staticfiles': {
|
|
282
|
+
'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage',
|
|
283
|
+
},
|
|
284
|
+
'finder_public': {
|
|
285
|
+
'BACKEND': 'finder.storage.FinderSystemStorage',
|
|
286
|
+
'OPTIONS': {
|
|
287
|
+
'location': '/path/to/your/media/filer_public',
|
|
288
|
+
'base_url': '/media/filer_public/',
|
|
289
|
+
'allow_overwrite': True,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
'finder_public_samples': {
|
|
293
|
+
'BACKEND': 'finder.storage.FinderSystemStorage',
|
|
294
|
+
'OPTIONS': {
|
|
295
|
+
'location': '/path/to/your/media/filer_public_thumbnails',
|
|
296
|
+
'base_url': '/media/filer_public_thumbnails/',
|
|
297
|
+
'allow_overwrite': True,
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
If instead of using the local file system you want to use another storage backend, such as MinIO,
|
|
304
|
+
Amazon S3 or Google Cloud Storage, configure the corresponding storage backend in the `STORAGES`
|
|
305
|
+
setting as:
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
STORAGES = {
|
|
309
|
+
...
|
|
310
|
+
'finder_public': {
|
|
311
|
+
'BACKEND': 'storages.backends.s3.S3Storage',
|
|
312
|
+
'OPTIONS': {...},
|
|
313
|
+
},
|
|
314
|
+
'finder_public_samples': {
|
|
315
|
+
'BACKEND': 'storages.backends.s3.S3Storage',
|
|
316
|
+
'OPTIONS': {...},
|
|
317
|
+
},
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Note that multiple root folders can share the same storage location or bucket.
|
|
322
|
+
|
|
323
|
+
If you declare neither `finder_public` nor `finder_public_samples`, finder derives them
|
|
324
|
+
from your `default` storage on startup: same filesystem root and URL prefix, but a
|
|
325
|
+
subdirectory per alias, the `FinderSystemStorage` backend and `allow_overwrite` turned on.
|
|
326
|
+
With Django's defaults that gives you
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
MEDIA_ROOT/finder_public/ served from MEDIA_URL + finder_public/
|
|
330
|
+
MEDIA_ROOT/finder_public_samples/ served from MEDIA_URL + finder_public_samples/
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
which is enough to get started. Declare them yourself once you want the files somewhere
|
|
334
|
+
else — on S3, on another volume, or shared between projects.
|
|
335
|
+
|
|
336
|
+
> [!NOTE]
|
|
337
|
+
> The derivation needs a `FileSystemStorage` as your `default`. If that is a remote
|
|
338
|
+
> backend there is no location to put a subdirectory under, and `manage.py check` reports
|
|
339
|
+
> `finder.W001`. Declare the two storages explicitly in that case.
|
|
340
|
+
|
|
341
|
+
Run the migrations for app `finder`:
|
|
342
|
+
|
|
343
|
+
```shell
|
|
344
|
+
python manage.py migrate finder
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
This creates a first ambit for you, so that the admin and the form widgets work right away.
|
|
348
|
+
It is named by `FINDER_DEFAULT_AMBIT`, which is `"public"` — the slug the
|
|
349
|
+
`FinderFileField`s and `FinderFolderField`s of your models refer to when they declare no
|
|
350
|
+
ambit of their own. Override it if you want a different name:
|
|
351
|
+
|
|
352
|
+
```python
|
|
353
|
+
FINDER_DEFAULT_AMBIT = 'assets'
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Its root folder grants read/write to everybody, which is the same thing
|
|
357
|
+
`manage.py finder add-ambit` does. Restrict it through the permission editor in the admin,
|
|
358
|
+
or set up the ambits yourself instead:
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
FINDER_CREATE_DEFAULT_AMBIT = False
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
The setting is only read while `finder.0001_initial` is applied, so it has to be in
|
|
365
|
+
place before you migrate for the first time.
|
|
366
|
+
|
|
367
|
+
Create further ambits with the configuration above:
|
|
368
|
+
|
|
369
|
+
```shell
|
|
370
|
+
python manage.py finder add-ambit private --values name="Private Folder" storage=finder_private sample_storage=finder_private_samples
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
You can create multiple root folders, each with their own unique slug and name. You may configure a
|
|
374
|
+
storage backend for each root folder or share them between multiple root folders.
|
|
375
|
+
|
|
376
|
+
If you already have **django-filer** installed and that database is filled, you can migrate the
|
|
377
|
+
meta-data of those files and folders into the new database tables. The physical files on disk are
|
|
378
|
+
not affected by this migration. Remember to leave the `filer` app in `INSTALLED_APPS`.
|
|
379
|
+
|
|
380
|
+
```shell
|
|
381
|
+
python manage.py filer_to_finder
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
This does not affect the original database tables. You can still use the original **django-filer**
|
|
385
|
+
codebase in parallel to the new "Finder" branch. They both share the same underlying file system,
|
|
386
|
+
usually `media/filer_public` but store their meta information in completely independent database
|
|
387
|
+
tables. The only caveat is that you should not erase files in the trash folder, because then they
|
|
388
|
+
are also gone on disk.
|
|
389
|
+
|
|
390
|
+
The client part of the new admin user must be compiled before it can be used. This requires a modern
|
|
391
|
+
version (18 or later) of [Node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/), which usually are installed anyway.
|
|
392
|
+
The following commands installs the requirements and compiles the code:
|
|
393
|
+
|
|
394
|
+
```shell
|
|
395
|
+
cd django-filer
|
|
396
|
+
npm install --include=dev
|
|
397
|
+
npm run buildall
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
## Usage
|
|
402
|
+
|
|
403
|
+
After restarting the development server, you can access the new admin user interface at the URL
|
|
404
|
+
http://localhost:8000/admin/finder/foldermodel/ . Clicking on that link will redirect you to the
|
|
405
|
+
root folder of the current site.
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
## Admin Backend
|
|
409
|
+
|
|
410
|
+
The admin backend is implemented as a web interface mimicking the features of the Finder app of your
|
|
411
|
+
operating system's graphical user interface. It is possible to …
|
|
412
|
+
|
|
413
|
+
* Download, upload files and to view them as thumbnailed images.
|
|
414
|
+
* Navigate through the folder tree by double-clicking on a folder.
|
|
415
|
+
* Move files and folders by drag and drop.
|
|
416
|
+
* Select multiple files and folders by a rectangular selection with the mouse.
|
|
417
|
+
* Cut or copy files and folders to a clipboard and paste them into another folder.
|
|
418
|
+
* Delete files and folders, which are moved to a trash folder.
|
|
419
|
+
* Restore files and folders from the trash folder or to delete them permanently.
|
|
420
|
+
* Create new folders and to upload files.
|
|
421
|
+
* Rename files and folders by slowly double-clicking on their name.
|
|
422
|
+
* Create multiple tabs for favourite folders quick access. They also can be used to drag files from
|
|
423
|
+
the current view into one of the tabs.
|
|
424
|
+
* Search for files and folders.
|
|
425
|
+
* Tag files and filter them by their tags.
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
## Interface to other Django projects
|
|
429
|
+
|
|
430
|
+
**django-filer** (Finder branch) ships with a new file selection field. This field can be used in
|
|
431
|
+
any Django model. It allows to select a file from the files stored inside **django-filer**. It also
|
|
432
|
+
allows to upload a local file and use it immediatly.
|
|
433
|
+
|
|
434
|
+
Example:
|
|
435
|
+
|
|
436
|
+
```python
|
|
437
|
+
from django.db import models
|
|
438
|
+
from finder.models.fields import FinderFileField
|
|
439
|
+
|
|
440
|
+
class MyModel(models.Model):
|
|
441
|
+
my_file = FinderFileField(
|
|
442
|
+
null=True,
|
|
443
|
+
blank=True,
|
|
444
|
+
ambit='my-ambit', # this must be the slug of an existing ambit
|
|
445
|
+
)
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Forms generated from this model will have a file selection widget for the `my_file` field. When
|
|
449
|
+
rendered as HTML, this widget becomes the webcomponent `<finder-file-select …></finder-file-select>`
|
|
450
|
+
with a few additional attributes. The JavaScript part of the widget must be included using the
|
|
451
|
+
script tag `<script src="{% static 'finder/js/finder-select.js' %}"></script>`.
|
|
452
|
+
|
|
453
|
+
The demonstration app provides an example how this field can be used in a form. Just vist the URL
|
|
454
|
+
http://localhost:8000/demoapp/ and click on the blank area to either select an existing file or
|
|
455
|
+
upload a new one.
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
## Thumbnailing
|
|
459
|
+
|
|
460
|
+
In addition to the x- and y-coordinates of the focal point, the `ImageModel` now also stores the
|
|
461
|
+
main area of interest as a square. This information then is used to create thumbnails using
|
|
462
|
+
[Art Direction](https://www.smashingmagazine.com/2016/01/responsive-image-breakpoints-generation/).
|
|
463
|
+
|
|
464
|
+
The method `finder.contrib.image.pil.models.ImageModel.crop()` creates a thumbnail of the given
|
|
465
|
+
image taking the focal point and the resolution into account. The following rules apply when
|
|
466
|
+
cropping and thumbnailing an image:
|
|
467
|
+
|
|
468
|
+
* The thumbnailed image always contains at least the main area of interrest, except for this
|
|
469
|
+
situation: If the thumbnail is narrower than the main area of interest, the thumbnail will be
|
|
470
|
+
cropped to the center of that area.
|
|
471
|
+
* The resolution of the area to be thumbnailed is always at least the same as the resolution of the
|
|
472
|
+
original image.
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
will take the resolution of the corresponsding image into
|
|
476
|
+
consideration. This will allow to create different versions of the same canonical image, depending
|
|
477
|
+
on the width of the device the image is displayed.
|
|
478
|
+
|
|
479
|
+
By extending the focal point to three degrees of freedom, it is possible to create a thumbnail
|
|
480
|
+
taking the resolution into account. This allows us to create thumbnails taking art direction into
|
|
481
|
+
consideration. For instance, if a user uploads a portrait image, the focal point can be set to the
|
|
482
|
+
head of the person in that image.
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
## Validating Uploads
|
|
486
|
+
|
|
487
|
+
Every uploaded payload is validated before it is written to storage. A validator is a callable
|
|
488
|
+
|
|
489
|
+
```python
|
|
490
|
+
def my_validator(file_name, file, owner, mime_type):
|
|
491
|
+
...
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
that raises `finder.exceptions.FileValidationError` to reject the upload. It is handed the uploaded
|
|
495
|
+
file rewound and opened for writing, so it may also **rewrite the content in place** rather than
|
|
496
|
+
reject it — that is how the bundled SVG sanitizer works. Rejecting a payload leaves nothing behind:
|
|
497
|
+
validation runs before the file reaches the storage backend.
|
|
498
|
+
|
|
499
|
+
This is deliberately the same contract django-filer uses for `FILER_ADD_FILE_VALIDATORS`, so
|
|
500
|
+
validators written for filer — including third-party ones — work here unchanged. A validator
|
|
501
|
+
signalling rejection with a plain `ValueError` is accepted too.
|
|
502
|
+
|
|
503
|
+
By default finder rejects the formats a browser executes in the media origin, and sanitizes SVG
|
|
504
|
+
uploads (which needs `py-svg-hush`, part of the `svg` extra):
|
|
505
|
+
|
|
506
|
+
| MIME-type | Validator |
|
|
507
|
+
|---|---|
|
|
508
|
+
| `text/html` | `finder.validators.deny_html` |
|
|
509
|
+
| `application/xhtml+xml`, `application/xml`, `text/xml`, `application/xslt+xml` | `finder.validators.deny` |
|
|
510
|
+
| `image/svg+xml` | `finder.contrib.image.svg.validators.sanitize_svg` |
|
|
511
|
+
|
|
512
|
+
Unlike django-filer, finder does **not** deny `application/octet-stream`: `FileModel` is the
|
|
513
|
+
documented fallback for everything that matches no other model, and browsers report that MIME-type
|
|
514
|
+
for plenty of harmless files. Add `{'application/octet-stream': ['finder.validators.deny']}` for
|
|
515
|
+
filer's behaviour.
|
|
516
|
+
|
|
517
|
+
Add your own validators with `FINDER_PAYLOAD_VALIDATORS`, a dict mapping a MIME-type to a list of
|
|
518
|
+
validators. The MIME-type may be exact, a subtype wildcard (`image/*`) or `*/*`; more general
|
|
519
|
+
matches run first. Values are dotted paths, callables or classes.
|
|
520
|
+
|
|
521
|
+
```python
|
|
522
|
+
FINDER_PAYLOAD_VALIDATORS = {
|
|
523
|
+
'image/*': ['myapp.validators.strip_exif'],
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Drop a default with `FINDER_REMOVE_PAYLOAD_VALIDATORS`, a list of MIME-types:
|
|
528
|
+
|
|
529
|
+
```python
|
|
530
|
+
FINDER_REMOVE_PAYLOAD_VALIDATORS = ['image/svg+xml']
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
## Further Steps
|
|
535
|
+
|
|
536
|
+
* A quota system, which allows to limit the amount of disk space a user can use.
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
## Further Readings
|
|
540
|
+
|
|
541
|
+
https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Responsive_images
|
|
542
|
+
https://www.smashingmagazine.com/2014/05/responsive-images-done-right-guide-picture-srcset/
|
|
543
|
+
https://www.smashingmagazine.com/2016/01/responsive-image-breakpoints-generation/
|
|
544
|
+
https://www.smashingmagazine.com/2016/09/automating-art-direction-with-the-responsive-image-breakpoints-generator/
|
|
545
|
+
https://cloudfour.com/thinks/responsive-images-101-part-9-image-breakpoints/
|
|
546
|
+
https://cloudfour.com/thinks/sensible-jumps-in-responsive-image-file-sizes/
|
|
547
|
+
|
|
548
|
+
https://cloudfour.com/thinks/the-real-conflict-behind-picture-and-srcset/
|
|
549
|
+
|
|
550
|
+
## License
|
|
551
|
+
|
|
552
|
+
This part of the code will be licensed under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|