Last active
November 26, 2016 10:46
-
-
Save gbezyuk/de29d4888818b87f8addd8143b5331e0 to your computer and use it in GitHub Desktop.
A mixin for customized to_dict() methods for Django models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from filebrowser.fields import FileBrowseField # not really a dependency, will be extracted before packaging | |
class ToDictMixin: | |
def to_dict(self): | |
opts = self._meta | |
data = {} | |
# initializing manually specified field grouping | |
if self.TO_DICT_GROUPING: | |
for prefix in self.TO_DICT_GROUPING: | |
data[prefix] = {} | |
# initializing prefixed field grouping | |
if self.TO_DICT_GROUPING_PREFIXES: | |
for prefix in self.TO_DICT_GROUPING_PREFIXES: | |
data[self._clean_grouping_prefix(prefix)] = {} | |
for f in opts.concrete_fields: | |
# skipping explicitly specified fields | |
if self.TO_DICT_SKIP_FIELDS: | |
if f.name in self.TO_DICT_SKIP_FIELDS: | |
continue | |
# handling prefixed fields grouping | |
if self.TO_DICT_GROUPING_PREFIXES: | |
prefix = self._get_grouping_prefix(f.name) | |
if prefix: | |
prefix_key = self._clean_grouping_prefix(prefix) | |
data[prefix_key][f.name.replace(prefix, '')] = f.value_from_object(self) | |
continue | |
# handling manually specified field grouping | |
if self.TO_DICT_GROUPING: | |
if f.name in self.TO_DICT_GROUPING.keys(): | |
data[f.name] = f.value_from_object(self) | |
continue | |
# handling images and other files | |
if type(f) == FileBrowseField: | |
data[f.name] = {} | |
try: | |
file = f.value_from_object(self) | |
if file: | |
data[f.name]['original'] = file.url | |
for version in FILEBROWSER_VERSIONS: | |
data[f.name][version] = file.version_generate(version).url | |
except FileNotFoundError: | |
data[f.name]['error'] = 'file not found' | |
# handling default case | |
else: | |
data[f.name] = f.value_from_object(self) | |
# cleanup for unused grouping | |
for k in [k for k in data.keys() if data[k] == {}]: | |
del data[k] | |
# the mixin allows to redifine the related fields strategy | |
if hasattr(self, '_to_dict_related_fields_strategy'): | |
self._to_dict_related_fields_strategy(opts, data) | |
else: | |
self._default_related_fields_strategy(opts, data) | |
# calling pre_finish_hook if exists | |
if hasattr(self, '_to_dict_pre_finish_hook'): | |
self._to_dict_pre_finish_hook(data) | |
return data | |
def _default_related_fields_strategy(self, opts, data): | |
related_fields = [f for f in opts.get_all_related_objects() if f.is_relation and f.multiple] | |
for rf in related_fields: | |
data[rf.name] = [i.to_dict() for i in getattr(self, rf.name).all()] | |
def _get_grouping_prefix(self, field_name): | |
if not self.TO_DICT_GROUPING_PREFIXES: | |
return None | |
for group_prefix in self.TO_DICT_GROUPING_PREFIXES: | |
if field_name.startswith(group_prefix): | |
return group_prefix | |
def _clean_grouping_prefix(self, prefix): | |
return prefix.replace('_', '') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment