Skip to content

Commit

Permalink
Added rest_framework fields and added model fields to admin formfield…
Browse files Browse the repository at this point in the history
…_to_dbfield registry and refactored validators.
  • Loading branch information
sakkada committed Apr 3, 2019
1 parent 5fc598c commit a71eef0
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 7 deletions.
2 changes: 1 addition & 1 deletion diverse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
- _get_image_dimensions
"""

VERSION = (0, 1, 1)
VERSION = (2, 0, 0)
Empty file added diverse/api/__init__.py
Empty file.
51 changes: 51 additions & 0 deletions diverse/api/rest_framework.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from rest_framework import fields


class DiverseFileField(fields.FileField):
# versions to representation as list or tuple, None means all,
# string means version as is (if original is not set to True)
dc_versions = None
# include original image as "self" key,
# to show only original as only url use regular file field
dc_original = False
# use default representation (only url), should be used in
# custom fileobj_to_representation method definition
dc_url_only = False

def __init__(self, *args, **kwargs):
self.dc_versions = kwargs.pop('versions', self.dc_versions)
self.dc_original = kwargs.pop('original', self.dc_original)
self.dc_url_only = kwargs.pop('url_only', self.dc_url_only)
super(DiverseFileField, self).__init__(*args, **kwargs)

def get_version_data(self, obj, version):
return

def fileobj_to_representation(self, obj):
return super(DiverseFileField, self).to_representation(obj)

def version_to_representation(self, obj, version):
return self.fileobj_to_representation(getattr(obj.dc, version))

def to_representation(self, obj):
data = None
if obj:
versions = self.dc_versions or obj.dc._versions.keys()
is_iterable = isinstance(versions, (list, tuple,))
if is_iterable or self.dc_original:
data = dict(
(i, self.version_to_representation(obj, i),)
for i in (versions if is_iterable else [versions]))
if self.dc_original:
data.update(self=self.fileobj_to_representation(obj))
else:
data = self.version_to_representation(obj, versions)
return data


class DiverseImageField(DiverseFileField, fields.ImageField):
def fileobj_to_representation(self, obj):
url = super(DiverseImageField, self).fileobj_to_representation(obj)
return url if self.dc_url_only else {
'url': url, 'width': obj.width, 'height': obj.height,
}
9 changes: 9 additions & 0 deletions diverse/fields/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from django.db.models.fields.files import ImageField, ImageFieldFile
from django.utils.safestring import mark_safe
from django.core import checks
from django.contrib.admin.options import FORMFIELD_FOR_DBFIELD_DEFAULTS
from .forms import DiverseFormFileField, DiverseFormImageField
from .widgets import DiverseFileInput, DiverseImageFileInput
from .validators import isuploaded


Expand Down Expand Up @@ -214,3 +216,10 @@ def formfield(self, **kwargs):
kwargs['form_class'] = DiverseFormImageField
kwargs.update([(i, getattr(self, i, None)) for i in keys])
return super(DiverseFileField, self).formfield(**kwargs)


# Register fields to use custom widgets in the Admin
FORMFIELD_FOR_DBFIELD_DEFAULTS.update({
DiverseFileField: {'widget': DiverseFileInput,},
DiverseImageField: {'widget': DiverseImageFileInput,},
})
40 changes: 34 additions & 6 deletions diverse/fields/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
from django.template.defaultfilters import filesizeformat


def isuploaded(value):
def isuploaded(value, getfile=False):
# note: value may be FieldFile or UploadedFile (model field or form field
# validation respectively), if FieldFile - get _file attr as value
# validation respectively), if value is FieldFile - get _file attr
# as value (usually InMemoryUploadedFile instance)
if isinstance(value, FieldFile):
value = getattr(value, '_file', None)
return isinstance(value, UploadedFile)
return ((value if getfile else True)
if isinstance(value, UploadedFile) else None)


class BaseValidator(object):
Expand All @@ -22,7 +24,7 @@ def __call__(self, value):
raise NotImplementedError

def __eq__(self, other):
return isinstance(other, self.__class__) and self.code == other.code
raise NotImplementedError


@deconstructible
Expand Down Expand Up @@ -53,6 +55,13 @@ def __call__(self, value):
code=self.code
)

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
self.code == other.code and
self.min == other.min and self.max == other.max
)


@deconstructible
class MimetypeValidator(BaseValidator):
Expand All @@ -61,19 +70,29 @@ class MimetypeValidator(BaseValidator):
def __init__(self, mimetypes=None):
if not mimetypes:
raise ValueError(u'There is not any allowed mimetypes for check.')
if isinstance(mimetypes, str):
mimetypes = (mimetypes,)
self.mimetypes = mimetypes

def __call__(self, value):
if not isuploaded(value):
value = isuploaded(value, getfile=True)
if not value:
return
mimetype = getattr(value.file, 'content_type', None)
mimetype = getattr(value, 'content_type', None)
if mimetype and mimetype not in self.mimetypes:
raise ValidationError(
_('Filetype "%(curr)s" is not allowed. Available types - [%(list)s].')
% {'curr': mimetype, 'list': str(', '.join(self.mimetypes))},
code=self.code
)

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
self.code == other.code and
self.mimetypes == other.mimetypes
)


@deconstructible
class ExtensionValidator(BaseValidator):
Expand All @@ -82,6 +101,8 @@ class ExtensionValidator(BaseValidator):
def __init__(self, extensions=None):
if not extensions:
raise ValueError(u'There is not any allowed extensions for check.')
if isinstance(extensions, str):
extensions = (extensions,)
self.extensions = extensions

def __call__(self, value):
Expand All @@ -95,3 +116,10 @@ def __call__(self, value):
% {'curr': extension, 'list': str(', '.join(self.extensions))},
code=self.code
)

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
self.code == other.code and
self.extensions == other.extensions
)

0 comments on commit a71eef0

Please sign in to comment.