-
-
Save piterskikhsa/4a3b7513b0c772c46fde62d7e1d42a44 to your computer and use it in GitHub Desktop.
Mixin for creating serializers with configurable fields (for the django rest framework).
This file contains hidden or 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
| """ | |
| Some helper serializer mixins. | |
| Helps to reuse serializers for different purposes. | |
| """ | |
| import logging | |
| from rest_framework import serializers | |
| LOGGER = logging.getLogger(__name__) | |
| class UpdateFieldsMixin(object): | |
| """ | |
| This mixin allows to update existing fields of a serializer. | |
| Basically it could be used to update type of a field without changing serializer. | |
| `update_fields` argument should be a list/tuple of field name and its definition. | |
| E.g. `update_fields = (('is_active', serializers.BooleanField(default=False)), ) | |
| """ | |
| def __init__(self, *args, **kwargs): | |
| fields = kwargs.pop('update_fields', None) | |
| super(UpdateFieldsMixin, self).__init__(*args, **kwargs) | |
| if fields and isinstance(fields, (list, tuple)): | |
| init_fields = {x[0]: x[1] for x in fields if len(x) == 2} | |
| self.fields.update(init_fields) | |
| class SetFieldsMixin(object): | |
| """ | |
| This mixin allows to change serializable fields in run time | |
| (when creating the instance). | |
| Just pass a list/tuple with names of fields that you want to | |
| serialize (as the `field` argument). | |
| It also could add new fields using same idea as in `UpdateFieldsSerialzier`. | |
| TODO: DRY | |
| """ | |
| def __init__(self, *args, **kwargs): | |
| fields = kwargs.pop('fields', None) | |
| super(SetFieldsMixin, self).__init__(*args, **kwargs) | |
| if fields and isinstance(fields, (list, tuple)): | |
| new_fields = [] | |
| init_fields = {} | |
| for field in fields: | |
| if not isinstance(field, tuple): | |
| new_fields.append(field) | |
| continue | |
| if len(field) != 2: | |
| continue | |
| init_fields[field[0]] = field[1] | |
| existing_fields = set(self.fields.keys()) | |
| for field in existing_fields - set(new_fields): | |
| self.fields.pop(field) | |
| for name, value in init_fields.items(): | |
| self.fields[name] = value | |
| class ExcludeFieldsMixin(object): | |
| """ | |
| This mixin allows to specify fields to be excluded from serializers | |
| in runtime (at initialization of serializer instance). | |
| Opposite of `SetFieldsMixin` | |
| """ | |
| def __init__(self, *args, **kwargs): | |
| excluded_fields = kwargs.pop('exclude_fields', None) | |
| super(ExcludeFieldsMixin, self).__init__(*args, **kwargs) | |
| if excluded_fields and isinstance(excluded_fields, (list, tuple)): | |
| excluded_fields = set(excluded_fields) & set(self.fields.keys()) | |
| for field in excluded_fields: | |
| self.fields.pop(field) | |
| class ConfigurableSerializer( | |
| SetFieldsMixin, | |
| ExcludeFieldsMixin, | |
| UpdateFieldsMixin, | |
| serializers.Serializer): | |
| def __init__(self, *args, **kwargs): | |
| super(ConfigurableSerializer, self).__init__(*args, **kwargs) | |
| class ConfigurableModelSerializer( | |
| SetFieldsMixin, | |
| ExcludeFieldsMixin, | |
| UpdateFieldsMixin, | |
| serializers.ModelSerializer): | |
| def __init__(self, *args, **kwargs): | |
| super(ConfigurableModelSerializer, self).__init__(*args, **kwargs) | |
| # Here is an example of how to use this mixin. | |
| # | |
| # class DashboardMetaSerializer(ConfigurableSerializer): | |
| # isStarred = rest_serializers.BooleanField(default=False) | |
| # isHome = rest_serializers.BooleanField(default=False) | |
| # isSnapshot = rest_serializers.BooleanField(default=False) | |
| # slug = rest_serializers.SlugField() | |
| # | |
| # Let's test it | |
| # | |
| # In [2]: from django_grafana.grafana import serializers | |
| # In [3]: s = serializers.DashboardMetaSerializer() | |
| # In [4]: s.data | |
| # Out[4]: {'isHome': False, 'isStarred': False, 'slug': u'', 'isSnapshot': False} | |
| # In [5]: s = serializers.DashboardMetaSerializer(fields=('isHome', 'slug')) | |
| # In [6]: s.data | |
| # Out[6]: {'isHome': False, 'slug': u''} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment