django-cabinet - Media library for Django¶
Version 0.14.3
django-cabinet is a media library for Django implemented while trying to write as little code as possible to keep maintenance at a minimum. At the time of writing the projects consists of less than 1000 lines of code (excluding tests), but still offers hierarchical folders, downloads, images with primary point of interest (courtesy of django-imagefield) and drag-drop uploading of files directly into the folder view.
Screenshots¶
Installation¶
pip install django-cabinet
Add
cabinet
andimagefield
to yourINSTALLED_APPS
Maybe replace the file model by setting
CABINET_FILE_MODEL
, but the default should be fine for most uses.
High-level overview¶
django-cabinet comes with two concrete models, cabinet.File
and
cabinet.Folder
.
Folders can be nested into a hierarchy.
Files by default have two file fields, one for images based on
django-imagefield and one for downloads, a standard Django
FileField
. Exactly one field has to be filled in. Files can only be
added to folders; files can never exist in the root folder.
Using cabinet files in your models¶
The recommended way to use cabinet files in your models is by using
cabinet.fields.CabinetForeignKey
. When using raw_id_fields
for
the file foreign key you automatically get an improved widget which 1.
allows directly uploading files inline without having to open the
raw_id_fields
popup and 2. also displays small thumbnails for image
files.
Using django-cabinet as a CKEditor filebrowser¶
django-cabinet has built-in support for being used as a CKEditor 4 file manager. Currently, it only supports browsing files or images. Directly uploading files isn’t supported since the file browser API does not know about cabinet’s folders and folders are required for adding files to cabinet.
The values for using django-cabinet as a file and image browser follow (assuming you’re using the default file model):
CKEDITOR.config.filebrowserBrowseUrl = "/admin/cabinet/file/?_popup=1";
CKEDITOR.config.filebrowserImageUrl = "/admin/cabinet/file/?_popup=1&file_type=image_file";
Replacing the file model¶
The file model is swappable, and should be easy to replace if you require additional or different functionality. If, for example, you’d want to move all PDFs to a different storage, build on the following example code.
First, models.py
:
from django.db import models
from django.db.models import signals
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from cabinet.base import AbstractFile, ImageMixin, DownloadMixin
class PDFMixin(models.Model):
pdf_file = models.FileField(
_('pdf'),
upload_to=...,
storage=...,
blank=True,
)
class Meta:
abstract = True
verbose_name = _("PDF")
verbose_name_plural = _("PDFs")
# Cabinet requires a accept_file method on all mixins which
# have a file field:
def accept_file(self, value):
if value.name.lower().endswith('.pdf'):
self.pdf_file = value
return True
class File(AbstractFile, ImageMixin, PDFMixin, DownloadMixin):
FILE_FIELDS = ['image_file', 'pdf_file', 'download_file']
# Add caption and copyright, makes FileAdmin reuse easier.
caption = models.CharField(
_('caption'),
max_length=1000,
blank=True,
)
copyright = models.CharField(
_('copyright'),
max_length=1000,
blank=True,
)
# Add additional fields if you want to.
# If files should be automatically deleted (this is also the case when
# using the default file model):
@receiver(signals.post_delete, sender=File)
def delete_files(sender, instance, **kwargs):
instance.delete_files()
Next, admin.py
:
# You do not have to build on top of FileAdmin, but if there's no
# good reason not to it's probably much less work. If not, you
# still should take a long look at cabinet.base_admin.FileAdminBase
from django.contrib import admin
from cabinet.admin import FileAdmin
from .models import File
# The default should probably work fine.
admin.site.register(File, FileAdmin)
Then, add CABINET_FILE_MODEL = 'yourapp.File'
to your Django
settings and at last you’re ready for running ./manage.py
makemigrations
and ./manage.py migrate
.
Change log¶
Next version¶
Added a Turkish translation. Thanks @mcihad!
Added the
extra_context
argument to ourchangelist_view
. Thanks @underdoeg!
0.14 (2024-02-02)¶
Added Django 5.0, Python 3.12.
Updated the pre-commit hooks and added ESLint again (it was inadvertently dropped).
Dropped the unique constraint on folder name per subfolder. Duplicate names are a minor issue compared to the integrity errors which happen while loading fixtures.
0.13 (2023-07-21)¶
Added Django 4.1 and 4.2 to the CI matrix.
Added Python 3.11.
Switched to ruff and hatchling.
Documented that you should add a
post_delete
handler yourself when replacing the default file model.Fixed a problem where the folder filter stopped working in the upcoming Django 5.0.
0.12 (2022-09-19)¶
Fixed a bug where mixins couldn’t be used as base classes of a custom file model.
Changed the file admin to never collapse the advanced fieldset by default.
Switched from Travis CI to GitHub actions.
Fixed a regression where the CKEditor plugin’s
forms.Media
declaration was missing the jQuery dependency.Specified the default
AutoField
for django-cabinet to avoid migrations.Added an additional safeguard against unhandleable images.
Fixed the
default_app_config
deprecation warning.Raised the minimum versions of Python to 3.8 and Django to 3.2.
0.11 (2020-09-12)¶
Verified compatibility with Django 3.1 and Python 3.8 (no changes necessary).
Removed
skipIf
statements from the testsuite still referencing Django < 1.11.Switched the testsuite to using sqlite3 instead of PostgreSQL. django-tree-queries supports different databases
Dropped Python 3.4 from the testsuite.
Updated ESLint and prettier used to format and check the CSS/JavaScript code.
Added isort.
0.10 (2019-12-19)¶
Changed files and folders to reuse more of django-tree-queries.
Made our inline upload JavaScript specify its dependency on
django.jQuery
.Verified compatibility with Django 3.0.
Changed the abstract file model to protect files against cascading folder deletions.
0.9 (2019-04-15)¶
Changed
CabinetForeignKey
to reference the configured file model by default.Limited the maximum width of the inline folder select widget.
Added tests for the
CabinetForeignKey
.Hardened the file upload route a bit.
Removed a leftover call to versatileimagefields’
delete_all_created_images
function.Improved test coverage, mainly by actually writing more tests.
Changed
reverse
call sites to explicitly specifycurrent_app
.Implemented optional autoselection of the last visited folder by explicitly specifying
?folder__id__exact=last
.Made
CabinetForeignKey
automatically open the last folder for new files.Dropped compatibility with Django 1.8 again.
Made our JS files’ dependency on
django.jQuery
explicit.Raised the length of file fields from
100
to1000
.
0.8 (2018-12-14)¶
Fix a problem where newer Django versions would crash because of a missing
inline_admin_formsets
variable in the admin change form context.Fixed the folder hierarchy loop detection to not enter an infinite loop itself.
Fixed the breadcrumbs parent folder links.
Also prevented root folders with same name.
Added django-tree-queries for helping manage the folder tree.
Made search only search the current folder and its descendants.
Changed
OverwriteMixin
to only overwrite files once as intended.Fixed a crash when moving several files at once with newer Django versions.
Reinstated the PPOI functionality in the default file admin interface.
Added a
cabinet.fields.CabinetForeignKey
drop-in replacement which extends theraw_id_fields
administration interface with a direct upload facility.Added configuration to make running prettier and ESLint easy.
Added compatibility with Django 1.8 so that migrating files from prehistoric django-filer versions gets easier.
Added more visible UI to upload several files at once.
Added timestamps to folders and files.
Added support for using django-cabinet as a CKEditor filebrowser.
Changed
FileAdmin.get_fieldsets
to automatically generate fitting fieldsets using the file mixins’ verbose name and editable fields.Added a filter for only showing files of a certain type.
Improved test coverage a bit and updated the documentation after actually using a swappable file model in a project.
Fixed a crash when an invalid primary key was specified as a query parameter in the admin changelist.
Modified responses when adding or editing files to always redirect to the containing folder instead of the root folder.
Fixed a possible crash when setting
_overwrite
to true but uploading no new file.
0.7 (2018-03-28)¶
Switched the image field from django-versatileimagefield to django-imagefield. The latter uses the same database layout as the former, but there are differences when it comes to image generation and generating thumbnail URLs.
0.6 (2018-03-18)¶
Changed
admin_details
to not include superfluous<br>
tags.Changed the
accept_file
methods on file mixins to return bools and not raise exceptions.Fixed the
OverwriteMixin
to calldelete_files
so that e.g. theimagefield
gets a chance of removing stale thumbnails.Dropped the useless
AbstractFile
, and renamedAbstractFileBase
toAbstractFile
.Added a guide on how to swap out the file model.
Added a hint to the files changelist that drag-drop upload is possible.
Disabled the drag-drop upload on the root folder (which would not have worked anyway, because files cannot be added to the root folder).
Added
unify
so that only one quoting style is used in the code.Changed the order of
accept_file
methods called to the order ofFILE_FIELDS
instead of the MRO (resp. the classes where the file fields are defined initially).Fixed the double saves in
OverwriteMixin
, and hopefully avoided edge case-y problems withdelete_files
.
0.5 (2018-03-13)¶
Made the folder CRUD functionality preserve query parameters so that
raw_id_fields
popups work seamlessly.Fixed the changelist to not crash when images are broken.
Changed the admin fieldsets to only show fields related to one file type when a cabinet file is filled in already.
Fixed a bug where adding subfolders would succeed, but redirect to the root folder.
Added an admin action for moving multiple files at once to a different folder.
0.4 (2017-07-04)¶
Made file model mixins determine themselves whether they can accept an upload or not.
Refactoring and code cleanups.
Tweaked the file list a bit.
0.3 (2017-06-21)¶
Added upload progress (only files, not bytes).
Implemented cleaning of storage when deleting and replacing files.
0.2 (2017-06-21)¶
Allow replacing files remotely.
Added caption, copyright and alt text fields.
Also show folder breadcrumbs when adding files.
Drag-drop upload of files directly into the folder view.
0.1 (2017-06-20)¶
Initial public version.