Created
September 28, 2024 09:09
-
-
Save gimntut/6e9241b7b4b92ee79de7fa8b3f88a8f4 to your computer and use it in GitHub Desktop.
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
from typing import Type, TYPE_CHECKING, TypeVar | |
from django.utils import timezone | |
from rest_framework.fields import Field | |
from rest_framework.serializers import ListSerializer | |
T = TypeVar("T") | |
def mixin_for(_: T) -> T: | |
# https://dev.to/gimntut/-1ohb | |
return object | |
class DataSerializerField(Field): | |
"""Сериализатор для вычисляемых данных""" | |
def __new__( | |
cls, serializer: Type["SerializerType"], *args, method_name=None, **kwargs | |
) -> "SerializerType": | |
class GetAttributeMixin(mixin_for(Field)): | |
def get_attribute(self, instance): | |
if self.source_attrs: | |
value = super().get_attribute(instance) | |
else: | |
default_method_name = f"get_{self.field_name}_data" | |
attr_name = method_name or default_method_name | |
method = getattr(self.parent, attr_name, None) | |
if not method: | |
raise AttributeError( | |
f"Не найден метод {attr_name} в классе {type(self.parent).__name__}" | |
) | |
value = method(instance) | |
return value | |
class_name = f'{serializer.__name__.replace("Serializer", "")}DataSerializer' | |
list_serializer_class = type("DataListSerializer", (GetAttributeMixin, ListSerializer), {}) | |
parent_meta_class = getattr(serializer, "Meta", object) | |
ref_name = class_name + str(int(timezone.now().timestamp() * 100000)) | |
meta_class = type( | |
"Meta", | |
(parent_meta_class,), | |
{"list_serializer_class": list_serializer_class, "ref_name": ref_name}, | |
) | |
data_serializer_class = type( | |
class_name, (GetAttributeMixin, serializer), {"Meta": meta_class} | |
) | |
kwargs.setdefault("source", "*") | |
kwargs["read_only"] = True | |
kwargs["required"] = False | |
return data_serializer_class(**kwargs) | |
if TYPE_CHECKING: | |
from utils.api.typing import SerializerType |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment