Skip to content

Instantly share code, notes, and snippets.

@jourdanrodrigues
Created August 10, 2021 12:21
Show Gist options
  • Save jourdanrodrigues/6d8dcca9825163e3572b724a933bfe2d to your computer and use it in GitHub Desktop.
Save jourdanrodrigues/6d8dcca9825163e3572b724a933bfe2d to your computer and use it in GitHub Desktop.
from typing import Dict, Generator, List, Union
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.fields import empty
class EnhancedModelSerializer(serializers.ModelSerializer):
Meta: type
def __init__(
self,
instance=None,
data=empty,
exclude: List[str] = None,
skip_validation: bool = False,
**kwargs,
):
super().__init__(instance, data, **kwargs)
self.__skip_validation = skip_validation
self.__exclude_fields = exclude or []
def to_internal_value(self, data):
if self.__skip_validation:
return data.copy()
return super().to_internal_value(data)
def get_excluded_fields(self) -> List[str]:
return self.__exclude_fields
@property
def _writable_fields(self) -> Generator[serializers.Field, None, None]:
for field in self.get_writable_fields().values():
yield field
def get_writable_fields(self) -> Dict[str, serializers.Field]:
excluded = set(self.get_excluded_fields() + self._get_write_once_field_names())
return {
name: field
for name, field in self.fields.items()
if not (field.read_only or name in excluded)
}
def _get_write_once_field_names(self) -> List[str]:
if self.instance is None:
return []
return getattr(self.Meta, "write_once", [])
@property
def _readable_fields(self) -> Generator[serializers.Field, None, None]:
for field in self.get_readable_fields().values():
yield field
def get_readable_fields(self) -> Dict[str, serializers.Field]:
excluded = set(self.get_excluded_fields())
return {
name: field
for name, field in self.fields.items()
if not (field.write_only or name in excluded)
}
def bind_field(
self,
fields: dict,
field_name: str,
field: serializers.Field,
) -> None:
if self.partial:
field.required = False
field.bind(field_name, None)
fields[field_name] = field
def get_request(self) -> Request:
return self.context["request"]
def get_action(self) -> Union[str, None]:
return getattr(self.context["view"], "action", None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment