Welcome to django-smartfields’s documentation!¶
Django Model Fields that are smart
This application introduces a totally new way of handling field’s values through unique ways they are assigned and processed. It is so simple that nothing needs to be done in order to start using it, yet it is so powerful, that it can handle automatic image and video file conversions with a simple specification of a conversion function. Check it out, and it will forever change the way you handle Model Fields.
Installation¶
pip install django-smartfields
Latest build¶
Forkme on Github: django-smartfields
Introduction¶
Here is a short introduction of how this app works and a simple example how it can be used.
First of all, as name suggests, it mainly deals with Model Fields, hence it is
supplied with a custom version of every Django’s Field. There is no difference
form original versions of fields in terms of interaction with database, forms or
with any other Django codebase, so both kinds of fields can be used together
safely and interchangeably. Main distinction form Django’s fields is that all
smartfields accept a keyword argument dependencies
, which should be a list
of Dependency's
or
FileDependency's
.
Dependency is a concept that allows you to change the value of any field or an
attribute attached to the model instance, including the field Dependency which
it is specified for. Each Dependency handles the value from a field through
Processors which are functions that can be accepted as default
,
pre_processor
and processor
kwargs. An actual model attribute or a field
which a processed value will be assigned to is specified by one or none of the
kwargs suffix
and attname
. More details on those see documentation in
Dependencies and Processors sections,
but for now let’s see a couple of simple examples.
Example¶
Let’s say we have a Product model where a slug needs to be automatically generated from product’s name and also properly modified to look like a slug.
from django.db.models import models
from django.utils.text import slugify
from smartfields import fields
from smartfields.dependencies import Dependency
def name_getter(value, instance, **kwargs):
return instance.name
class Product(models.Model):
name = models.CharField(max_length=255)
slug = fields.SlugField(dependencies=[
Dependency(default=name_getter, processor=slugify)
])
Here is what will happen in above example whenever an instance of Product
is created:
- Whenever
Product
is initilized andslug
field is empty, it will attempt to get a value fromname
field. In case when it is still empty before model is being saved it will attempt to get the value again, all because ofdefault
functionname_getter
.- Right before the model is saved
processor
functionslugify
will be invoked, and value of the field fromname
will be modified to look like a slug. Important part is, processor will be invoked only whenever the value ofslug
field has changed.
Important Perculiarities¶
- Fields are processed in order they are specified in a Model.
- Dependencies are processed in the order they are speciefied in the
dependencies
list, except the ones withasync
flag, these are processed last, but also in the order they were specified.
More Details¶
Dependencies¶
-
class
smartfields.dependencies.
Dependency
¶ -
__init__
(attname=None, suffix=None, processor=None, pre_processor=None, async=False, default=NOT_PROVIDED, processor_params=None, uid=None)¶
Parameters: - attname (str) – Name of an attribute or an existing field that dependecy will assign a value to. Cannot be used together with suffix.
- suffix (str) – Will be used together with a field name in generating an attname in format field_name_suffix. Generated name can refer to an attribute or an existing field that dependecy will assign a value to. Cannot be used together with attname.
- processor – A function that takes field’s value as an argument or an
instance of a class derived from
BaseProcessor
. In a latter case it will receive all arguments:value
,instance
,field
,field_value
,dependee
,stashed_value
plus any custom kwargs. If a class is passed instead of it’s instance it will be instantiated, to prevent a common mistake. - pre_processor –
- async –
- default –
- processor_params –
- uid –
-
Processors¶
-
class
smartfields.processors.
BaseProcessor
¶ -
__init__
(**kwargs)¶
-
process
(value, instance=None, field=None, dependee=None, stashed_value=None, **kwargs)¶
Parameters: - value – New value that is being assigned to the parent field.
- instance – Model instance that a field is attached to.
- field – Parent field instance.
- dependee – Instance of a field that depends on the
field
. It is decided by theattname
orsuffix
argument to the - stashed_value – This is a previous value that a
dependee
field was holding. Very useful for comparing it to new values.
-
-
class
smartfields.processors.
RenameFileProcessor
¶
-
class
smartfields.processors.
ExternalFileProcessor
¶
Here is an examlple of how to convert a video to MP4 format. In this example
every time MediaModel
is instantiated
FileDependency
will automatically attach
another field like attribute to the model video_mp4
. Moreover, whenever a
new video file is uploaded or simply assigned to a video
field, it will use
FFMPEGProcessor
and ffmpeg
to convert
that video file to mp4 format and will assign it the same name as original video
with mp4
suffix and file extension. While converting a video file it will
set progress between 0.0 and 1.0, which can be retrieved from field’s status.
from django.db import models
from smartfields import fields, dependencies
from smartfields.processors import FFMPEGProcessor
class MediaModel(models.Model):
video = fields.FileField(dependencies=[
dependencies.FileDependency(suffix='mp4', processor=FFMPEGProcessor(
vbitrate = '1M',
maxrate = '1M',
bufsize = '2M',
width = 'trunc(oh*a/2)*2', # http://ffmpeg.org/ffmpeg-all.html#scale
height = 720,
threads = 0, # use all cores
abitrate = '96k',
format = 'mp4',
vcodec = 'libx264',
acodec = 'libfdk_aac'))])
Project Info¶
Changelog¶
1.1.2¶
- Support for Django=3.1.*
1.1.1¶
- Support for Django=3.0.*
1.1.0¶
1.0.7¶
- added
gis
fields. - made
lxml
a default parser for HTMLProcessor.
1.0.6¶
- added
RenameFileProcessor
1.0.5¶
- minor bug fixes.
1.0.4¶
- Switched to MIT License
- Added
stashed_value
to processors.
1.0.3¶
- Added support for
Wand
withWandImageProcessor
. - Made it compatible with Django 1.8
- Updated compiled JavaScript file.
1.0.2¶
- Introduced
pre_processor
. - Made
UploadTo
serializible. - Got rid of custom handlers.
- Minor bugfixes.
1.0.0¶
- Initial release
Authors¶
- Alexey Kuleshevich <lehins@yandex.ru> @lehins
License¶
The MIT License (MIT)
Copyright (c) 2015 Alexey Kuleshevich
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.