cdh.files.db.fields module

class cdh.files.db.fields.FileField(to=None, on_delete=None, to_field=None, db_constraint=True, filename_generator: callable = None, url_pattern: str = None, **kwargs)[source]

Bases: FileFieldCacheMixin, ForeignObject

A replacement for Django’s FileField. To the programmer, a File-like object is exposed which they can use to interact with the files.

The main advantages over Django’s FileField are:

  • If a file is removed from a model, it’s actually also removed from disk automatically. Django’s version leaves it where it is, taking up space

  • Files are not stored on disk using their original filename, an UUID is used instead as the filename. This makes guessing filenames next to impossible, providing a (small) layer of security.

  • In addition, by default this system will store files in a non-web facing location. (Or at least it should be). Accessing these files should be done through a download view, allowing the programmer to add permission checks.

Under the hood, it’s actually a modified ForeignKey to (a subclass of) File, which keeps track of the metadata. A custom descriptor is then used to wrap it in a FileWrapper instance, which provides a File-like interface and (alongside the descriptor and this field) handles the complicated DB interactions.

__init__(to=None, on_delete=None, to_field=None, db_constraint=True, filename_generator: callable = None, url_pattern: str = None, **kwargs)[source]
Parameters
  • to – A File-like model.

  • on_delete – See Django docs for ForeignKey

  • to_field – The field on File one should link to. Only change this when using a different model in ‘to’ please

  • db_constraint – See Django docs for ForeignKey

  • filename_generator – A callable which, given a FileWrapper, will return a name for the file. Note that this isn’t saved anywhere! Changing the callable will change the name of all existing files

  • kwargs – See Django docs for ForeignKey

attr_class

alias of FileWrapper

check(**kwargs)[source]
contribute_to_class(*args, **kwargs)[source]

Register the field with the model class it belongs to.

If private_only is True, create a separate instance of this field for every subclass of cls, even if cls is not an abstract model.

convert_empty_strings(value, expression, connection)[source]
db_check(connection)[source]

Return the database column check constraint for this field, for the provided connection. Works the same way as db_type() for the case that get_internal_type() does not map to a preexisting model field.

db_parameters(connection)[source]

Extension of db_type(), providing a range of different return values (type, checks). This will look at db_type(), allowing custom model fields to override it.

db_type(connection)[source]

Return the database column data type for this field, for the provided connection.

deconstruct()[source]

Return enough information to recreate the field as a 4-tuple:

  • The name of the field on the model, if contribute_to_class() has been run.

  • The import path of the field, including the class, e.g. django.db.models.IntegerField. This should be the most portable version, so less specific may be better.

  • A list of positional arguments.

  • A dict of keyword arguments.

Note that the positional or keyword arguments must contain values of the following types (including inner values of collection types):

  • None, bool, str, int, float, complex, set, frozenset, list, tuple, dict

  • UUID

  • datetime.datetime (naive), datetime.date

  • top-level classes, top-level functions - will be referenced by their full import path

  • Storage instances - these have their own deconstruct() method

This is because the values here must be serialized into a text format (possibly new Python code, possibly JSON) and these are the only types with encoding handlers defined.

There’s no need to return the exact way the field was instantiated this time, just ensure that the resulting field is the same - prefer keyword arguments over positional ones, and omit parameters with their default values.

default_error_messages = {'invalid': '%(model)s-instantie met %(field)s %(value)r bestaat niet.'}
description = 'Refererende sleutel (type wordt bepaald door gerelateerde veld)'
descriptor_class

alias of FileDescriptor

empty_strings_allowed = False
formfield(*, using=None, **kwargs)[source]

Pass limit_choices_to to the field being constructed.

Only passes it if there is a type that supports related fields. This is a similar strategy used to pass the queryset to the field being constructed.

alias of ForwardFileDescriptor

get_attname()[source]
get_attname_column()[source]
get_cache_name()[source]
get_col(alias, output_field=None)[source]
get_db_converters(connection)[source]
get_db_prep_save(value, connection)[source]

Return field’s value prepared for saving into a database.

get_db_prep_value(value, connection, prepared=False)[source]

Return field’s value prepared for interacting with the database backend.

Used by the default implementations of get_db_prep_save().

get_default()[source]

Return the to_field if the default value is an object.

get_prep_value(value)[source]

Perform preliminary non-db specific value checks and conversions.

get_reverse_path_info(filtered_relation=None)[source]

Get path from the related model to this field’s model.

many_to_many = False
many_to_one = True
one_to_many = False
one_to_one = False
post_delete(sender, instance, **kwargs)[source]
post_save(sender, instance, created, **kwargs)[source]

Handle deletion of a file

pre_delete(sender, instance, **kwargs)[source]
pre_save(model_instance, add)[source]

Make sure we save our file when saving the model this field is attached to

rel_class

alias of ManyToOneRel

property target_field

When filtering against this relation, return the field on the remote model against which the filtering should happen.

to_python(value)[source]

Convert the input value into the expected Python data type, raising django.core.exceptions.ValidationError if the data can’t be converted. Return the converted value. Subclasses should override this.

validate(value, model_instance)[source]

Validate value and raise ValidationError if necessary. Subclasses should override this to provide validation logic.

class cdh.files.db.fields.FileFieldCacheMixin[source]

Bases: object

Provide an API for working with the model’s fields value cache.

This is a modified version of Django’s FieldCacheMixin, which keeps track of the old

clear_cache(instance)[source]
delete_cached_value(instance)[source]
delete_value_from_cache(instance, value)[source]
get_cache_name()[source]
get_cached_value(instance, default=<object object>, all=False)[source]
in_cache(instance, value)[source]
is_cached(instance)[source]
set_cached_value(instance, value, clear=False)[source]
set_cls

alias of IndexedOrderedSet

class cdh.files.db.fields.TrackedFileField(to=None, related_name=None, related_query_name=None, limit_choices_to=None, file_kwargs: dict = None, db_constraint=True, db_table=None, swappable=True, url_pattern: str = None, **kwargs)[source]

Bases: ManyToManyField

__init__(to=None, related_name=None, related_query_name=None, limit_choices_to=None, file_kwargs: dict = None, db_constraint=True, db_table=None, swappable=True, url_pattern: str = None, **kwargs)[source]
attr_class

alias of TrackedFileWrapper

contribute_to_class(cls, name, **kwargs)[source]

Register the field with the model class it belongs to.

If private_only is True, create a separate instance of this field for every subclass of cls, even if cls is not an abstract model.

deconstruct()[source]

Return enough information to recreate the field as a 4-tuple:

  • The name of the field on the model, if contribute_to_class() has been run.

  • The import path of the field, including the class, e.g. django.db.models.IntegerField. This should be the most portable version, so less specific may be better.

  • A list of positional arguments.

  • A dict of keyword arguments.

Note that the positional or keyword arguments must contain values of the following types (including inner values of collection types):

  • None, bool, str, int, float, complex, set, frozenset, list, tuple, dict

  • UUID

  • datetime.datetime (naive), datetime.date

  • top-level classes, top-level functions - will be referenced by their full import path

  • Storage instances - these have their own deconstruct() method

This is because the values here must be serialized into a text format (possibly new Python code, possibly JSON) and these are the only types with encoding handlers defined.

There’s no need to return the exact way the field was instantiated this time, just ensure that the resulting field is the same - prefer keyword arguments over positional ones, and omit parameters with their default values.

description = 'File field with history tracking'
formfield(*, using=None, **kwargs)[source]

Pass limit_choices_to to the field being constructed.

Only passes it if there is a type that supports related fields. This is a similar strategy used to pass the queryset to the field being constructed.

rel_class

alias of TrackedFileRel

value_from_object(obj)[source]

Return the value of this field in the given model instance.

class cdh.files.db.fields.TrackedFileRel(field, to, related_name=None, related_query_name=None, limit_choices_to=None, db_constraint=True)[source]

Bases: ForeignObjectRel

Used by ManyToManyField to store information about the relation.

_meta.get_fields() returns this class to provide access to the field flags for the reverse relation.

__init__(field, to, related_name=None, related_query_name=None, limit_choices_to=None, db_constraint=True)[source]

Return the field in the ‘to’ object to which this relationship is tied. Provided for symmetry with ManyToOneRel.

property identity
cdh.files.db.fields.create_tracked_file_intermediary_model(field, cls, file_kwargs: dict)[source]