References

Preview

Any field which use the widget ClearableFileInputButton would have a specific look when editing.

_images/ClearableFileInputButton.png

Input got existing image preview with a checkbox to clear field value (and remove related file).

Obviously, there won’t be any preview or clear checkbox when field is empty. In this case only the upload button will be showed.

Widgets

Widgets are just about HTML and layout, nothing more. There are different widgets so use the one which fullfil your needs but to know ClearableFileInputButton is the most featured one.

The base versions does not include widget stylesheet and Javascript assets so you can include them yourself. This is helpful in some specific situations when you want to make layout integration yourself but commonly you will prefer the non-base widgets.

class smart_media.widgets.FileInputButtonBase(attrs=None)[source]

A simple FileInput override to use a custom template.

The custom template is located at smart_image/fileinputbutton_basic.html, you may override it in your project if needed, but mind it is global to all SmartMedia widgets.

Default behavior if no class attribute is given is to apply the CSS classname fileinputbutton__input to the input.

Note

When your input file enable the multiple attribute to accept more than one file, label input will be rendered to a default string like “4 files” which is not translatable (this is done in the Javascript source).

If you want a translatable string just pass it to widget instance attribute data-multiple-caption like:

FileInputButton(attrs={
    "data-multiple-caption": gettext_lazy("{count} files selected")
})

Pattern {count} will be replaced with the number of selected files.

class smart_media.widgets.ClearableFileInputButtonBase(attrs=None)[source]

Alike FileInputButtonBase but to extend with the additional clear checkbox.

This won’t support the “multiple” input file feature.

class smart_media.widgets.FileInputButton(attrs=None)[source]

FileInputButtonBase version which includes the required assets to customize its layout and turn the file input as a button.

This widget will define a stylesheet and a Javascript asset to load as form medias, this automatically done from admin but you will probably have to load them on your own in a custom form.

  • Stylesheet is located at smart_image/css/fileinputbutton.css (relative to static directory);

  • Javascript is located at smart_image/js/fileinputbutton.js (relative to static directory);

You can retrieve these assets sources in repository, note than the CSS is built from a Sass source you may copy into your project Sass sources.

class smart_media.widgets.ClearableFileInputButton(attrs=None)[source]

ClearableFileInputButtonBase version which includes the required assets to customize its layout and turn the file input as a button.

Form Fields

Form fields implement widgets for FileField and ImageField but they are less easy to use with a model form.

class smart_media.fields.SmartMediaField(*, max_length=None, allow_empty_file=False, **kwargs)[source]

A FileField which define the widget ClearableFileInputButton and default validator FileExtensionValidator for allowed extensions (as defined from setting SMARTIMAGE_ALLOWED_IMAGE_EXTENSIONS).

Note

Validation is pretty basic since it works on file extension, no malicious Bitmap or SVG image files would be detected here. If it is a concern, you will have to develop or use an additional validator.

widget

alias of ClearableFileInputButton

class smart_media.fields.SmartImageField(*, max_length=None, allow_empty_file=False, **kwargs)[source]

An ImageField which define the widget ClearableFileInputButton, the default validator is still the one from ImageField and so the field won’t allow for SVG file.

widget

alias of ClearableFileInputButton

Model Fields

class smart_media.modelfields.SmartMediaField(verbose_name=None, name=None, upload_to='', storage=None, **kwargs)[source]

A model file field with every “smart” features.

  • Set the SmartMediaFileExtensionValidator validator;

  • Use the form field SmartMediaField to get the proper “smart” clearable file widget;

  • Generate filename as an unique UUID with uploadto_unique function;

Example

Usage is identical to a models.FileField:

cover = SmartMediaField(
    "cover",
    max_length=255,
    null=True,
    blank=True,
    default=None,
    upload_to="sample/cover/%y/%m",
)

Note

If attribute upload_to value is a callable then the UUID filename behavior is disabled.

Note

Sadly this just won’t work on its own in Django admin which makes some internal resolutions between model fields and widgets. So you will need to define a rule to get the right widget for this field, see smart_media.admin.SmartModelAdmin.

Warning

Django won’t be able to detect change on settings. So you will have to create a custom data migration on your own if you want to clean files with previously allowed extensions but removed from setting.

generate_filename(instance, filename)[source]

Override FileField.generate_filename() to change original uploaded filename to an UUID.

‘upload_to’ date pattern is still properly formatted and the UUID behavior is ignored if ‘upload_to’ is a callable.

formfield(**kwargs)[source]

Return a django.forms.Field instance for this field.

Model signals

These signals are not mandatory but are very helpful to automatically clean your media directory from stall files.

They are on your own to implement in your models still it is very easy to do and do not require any migrations.

Warning

Purge signals can be harmful on very specific case if you blindly implement them without thinking about your application behaviors.

For example, it is known that plugins from DjangoCMS are cloned on each save, for this reason the signal auto_purge_files_on_delete must not be connected to a DjangoCMS plugin model because it deletes cloned object files without copying them first for new clone. It results on plugin objects keeping references to files that have been removed by the “on delete” purge signal (since cloning imply to copy then delete).

You need to think if your models are doing post processing saves on object.

smart_media.signals.auto_purge_files_on_delete(fieldnames)[source]

Return a callable to set as a signal receiver to purge related files from deleted object.

When connected to your model, just before an object is deleted the signal check defined fields for their files and remove them from your Filesystem so you won’t keep files from object that do not exists anymore.

This is to be used with signal django.db.models.signals.post_delete and since this work with shallow function you will need to set weak=False on signal method connect.

Example

Commonly you connect signal in your models file and define a list of fields to watch for purge:

from django.db import models
from django.db.models.signals import post_delete
from smart_media.signals import auto_purge_files_on_delete

class MyModel(models.Model):
    cover = models.FileField(...)

post_delete.connect(
    auto_purge_files_on_delete(["cover"]),
    dispatch_uid="mymodels_files_on_delete",
    sender=MyModel,
    weak=False,
)

Remember to set an unique key name to argument dispatch_uid.

Parameters:

fieldnames (list) – List of model field names to seek for file to remove. If a given field name does not exists for given model instance an exception is raised. It is important to keep this list up to date with your model.

Returns

callable: A callable function with expected signature from signal emitter.

smart_media.signals.auto_purge_files_on_change(fieldnames)[source]

Return a callable to set as a signal receiver to purge old related files for a modified object with new uploaded files.

When connected to your model, just before an existing object is saved the signal check defined fields for their current files, if a current file is different than the one from the changes, it is removed from your Filesystem so you won’t keep files that have been deleted or changed.

It is safe if old file does not exists anymore.

This is to be used with signal django.db.models.signals.pre_save and since this work with shallow function you will need to set weak=False on signal method connect.

This receiver perform an additional get queryset on object to get its previous value just before current save.

Example

Commonly you connect signal in your models file and define a list of fields to watch for purge:

from django.db import models
from django.db.models.signals import pre_save
from smart_media.signals import auto_purge_files_on_change

class MyModel(models.Model):
    cover = models.FileField(...)

pre_save.connect(
    auto_purge_files_on_change(["cover"]),
    dispatch_uid="mymodels_files_on_change",
    sender=MyModel,
    weak=False,
)

Remember to set an unique key name to argument dispatch_uid.

Parameters:

fieldnames (list) – List of model field names to seek for file to remove. If a given field name does not exists for given model instance an exception is raised. It is important to keep this list up to date with your model.

Returns

callable: A callable function with expected signature from signal emitter.

Django admin

class smart_media.admin.SmartAdminMixin[source]

A class to mix with a Django admin class to the use right widget definition for model field modelfields.SmartMediaField.

Note

This is required because ModelAdmin translate model fields to widgets using a list of harcoded relations between fields and widgets.

It results in field definitions from SmartMediaField.formfield to be ignored and SmartMediaField using admin widget AdminFileWidget instead of expected ClearableFileInputButton.

This mixin will be safe to use with specific model admins that does not allows to inherit from SmartModelAdmin.

Example

Your model admin just have to inherit from this class in addition to the model admin class:

from django.contrib import admin
from smart_media.admin import SmartAdminMixin
from myapp.models import MyModel

@admin.register(MyModel)
class MyModelAdmin(SmartAdminMixin, admin.ModelAdmin):
    ...

If you can’t use it, just copy the source of SmartAdminMixin.formfield_overrides (see source) into your own model admin.

class smart_media.admin.SmartModelAdmin(model, admin_site)[source]

A model admin class to include SmartAdminMixin.

It is only required with model forms in Django admin. If your model admin already inherit from a specific admin class, you will prefer to use the SmartAdminMixin.

Example

Your model admin just have to inherit from this class:

from django.contrib import admin
from smart_media.admin import SmartModelAdmin
from myapp.models import MyModel

@admin.register(MyModel)
class MyModelAdmin(SmartModelAdmin):
    ...

Template tags

There is a single template tag you would use in your template on model file fields to get a proper thumbnail for any supported format.

It uses Sorl library to build the thumbnail but opposed to the Sorl tag, media_thumb will keep the original format instead of converting it to a normalized one. This is useful to preserve image when you upload a transparent PNG or an animated GIF, it won’t be converted to a JPEG that would lose alpha channel or animation and may result to a weird thumbnail.

Also it will allows SVG format but without making a thumbnail since PIL don’t support it and vectorial image can be assumed to fit in any size.

Finally, be aware that you cannot convert Bitmap image to SVG and vice versa, so if you allow SVG, you need to let the argument format to auto value.

smart_media.templatetags.smart_image.media_thumb(source, geometry, *args, **kwargs)[source]

Determine the right format and return the Sorl thumb file url path for given image file.

Parameters:
  • source (object) – Either a FileField or an ImageField.

  • geometry (string) – Geometry string as expected by Sorl. It should be something like 200 for 200px width and automatic height or 200x100 for 200px width and 100px height.

  • *args – Not used, there is no other expected positionnal arguments.

  • **kwargs – Keyword arguments are passed to Sorl, watch its documentation for more details.

Keyword Arguments:

format (string) –

An available format name from settings SMART_FORMAT_AVAILABLE_FORMATS:

  • PNG, JPEG and GIF enforce the thumb format no matter the source image format. Be careful to not enforce a format where a SVG is a possible source format, since Sorl can’t read SVG.

  • SVG will not produce any thumb, just return the same path than the source one since SVG does not need a thumb and is not supported from image libraries.

  • auto to automatically find and use the same format than the source image. This is the recommended way.

When argument is empty the default value is auto.

Example

The most basic usage is to define only thumbnail geometry in default “auto” format mode:

{% load smart_image %}
{% media_thumb instance.image "250x200" as thumb %}
<img src="{{ thumb.url }}" alt="">

You can also enforce a specific format:

{% load smart_image %}
{% media_thumb instance.image "250x200" format="JPEG" as thumb %}
<img src="{{ thumb.url }}" alt="">

Keep it in mind this will raise an error with SVG image files (if you allowed SVG format in plugins) since image libraries (like Pillow or ImageMagick) has no support for SVG.

Every argument but format is passed to Sorl, so for cropping an image you can do :

{% load smart_image %}
{% media_thumb instance.image "250x200" crop="center" as thumb %}
<img src="{{ thumb.url }}" alt="">

Again, see Sorl documentation to know about available options.

Returns:

Either Sorl ImageFile instance for created thumb or SvgFile which mimic Sorl ImageFile.

Return type:

sorl.thumbnail.images.ImageFile or SvgFile

Mixin

A mixin object exists to get the right image format name. It is used internally in template tag but you can also inherit it from a model if you need this format name somewhere in your code.

class smart_media.mixins.SmartFormatMixin[source]

A mixin to inherit from a model so it will have a helper method to manage image formats.

Example

You just have to inherit this class then define a method dedicated to your field:

from django.db import models
from smart_media.mixins import SmartFormatMixin
from smart_media.modelfields import SmartMediaField

class MyModel(SmartFormatMixin, models.Model):
    media = SmartMediaField(
        "media",
        max_length=255,
        null=True,
        blank=True,
        default=None,
        upload_to="sample/media/%y/%m",
    )

    def get_media_format(self):
        return self.media_format(self.media)
media_format(mediafile)[source]

Common method to perform a naive check about image format using file extension.

Retrieved format will come from setting SMART_FORMAT_AVAILABLE_FORMATS.

Obviously since it use the file extension, found format is not to be 100% trusted. You may think about validate your files strictly if strong security is a matter for you and file upload is open to untrusted user.

Parameters:

mediafile (object) – Either a FileField, ImageField or any other object which implement a name attribute which return the filename.

Returns:

Format name if filename extension match to any available format extension from available formats else it returns None.

Return type:

string

SVG

To ensure compatibility for both Bitmap and SVG format, we aim to ensure template tag return can be used in the same way with thumbnail library.

So for a SVG file we return a SvgFile which implement basic attributes and methods alike Sorl ImageFile.

Note

Commonly you won’t have to deal with it directly so don’t bother anymore if you are not trying to implement something very specific.

class smart_media.thumbnailing.SvgFile(fileobject, storage=None)[source]

Object to mimic Sorl object thumbnail.images.ImageFile and implement some of its attributes and methods.

All other method about image size are not supported.

name

File name, aka its relative path from its storage.

Type:

string

url

Full media file url from its storage.

Type:

string

Parameters:

fileobject (django.core.files.File) – A valid Django file object.

Keyword Arguments:

storage (django.core.files.storage.FileSystemStorage) – Storage related to the file. If not given, the default Django storage backend is used.

Exceptions

Application parts may raise specific exceptions, it may be helpful to recognize them.

exception smart_media.exceptions.SmartImageBaseException[source]

Base for every SmartFormat template tag exceptions.

exception smart_media.exceptions.InvalidFormatError[source]

Exception to be raised from smart_format template tag when given format is not invalid.

exception smart_media.exceptions.IncompatibleSvgToBitmap[source]

Exception to be raised from smart_format template tag when required format is a Bitmap formt but the source is a SVG.

exception smart_media.exceptions.IncompatibleBitmapToSvg[source]

Exception to be raised from smart_format template tag when required format is a SVG but the source is a Bitmap.

Optional contributions

There you could find some useful optional contributions for some feature or packages.

class smart_media.contrib.django_configuration.SmartMediaDefaultSettings[source]

Default “Django smart media” settings class to use with a “django-configuration” class.

Example

You could use it like so:

from configurations import Configuration
from smart_media.contrib.django_configuration import (
    SmartMediaDefaultSettings,
)

class Dev(SmartMediaDefaultSettings, Configuration):
    DEBUG = True

    SMARTIMAGE_FILESIZE_LIMIT = 142

This will override only the setting SMARTIMAGE_FILESIZE_LIMIT, all other SmartMedia settings will have the default values from smart_media.settings.