Как вернуть данные из вложенных сериализаторов в сериализаторы, созданные на лету? - PullRequest
0 голосов
/ 01 декабря 2018

Недавно я пробовал что-то новое с Django, чтобы попытаться упростить написание ответов в представлениях, возможно, не стоит делать в конце, но мне все еще интересно посмотреть, можно ли это сделать.

Как правило, у нас будет следующий сериализатор для возврата обратной информации:

# serializers.py
class SomeDefinedSerializer(serializers.ModelSerializer):
    extra_model = SomeExtraModelSerializer()
    greet_name = serializers.SerializerMethodField()

    class Meta:
        model = SomeDefinedModel
        fields = ('name', 'age', 'field1', 'field2')

    def get_greet_name(self, obj):
        return f"Hello {obj.name}"

Теперь с этим определенным сериализатором мы можем вернуть просто нужных нам полей и затем предположитьв SomeExtraModelSerializer() мы определили подмножество полей, мы получаем хороший словарь значений с вызовом .data.

Но, делая это с крупномасштабными приложениями, мы в конечном итоге будем писать нагрузки и нагрузкииз сериализаторов, которые просто используются для конкретных задач, в результате чего много кода, который почти виртуально похож.Конечно, мы НЕ ДОЛЖНЫ делать это таким образом, мы могли бы создавать более общие сериализаторы, но это означает, что все различные задачи из внешнего интерфейса в итоге получают огромный избыток информации, что в действительности только небольшой процент данных получаетused.

Поэтому моей первоначальной идеей было создать базовый класс сериализатора, чтобы все другие сериализаторы основывались на нем с помощью пользовательского метода <strong>init</strong>, чтобы вы могли просто вызывать сериализатор и передавать какkwargs поля, которые вы хотите, или исключить ...

Но потом я подумал, но таким образом мы все еще должны определить сериализаторы для определенных задач.

Как насчет того, чтобы в представлениях django я мог определить сериализатор и его вложенные сериализаторы, все со своими собственными конкретными полями, которые я хочу вернуть, на лету, что бы вроде работало как:*

Итак, я написал основной способ, как это сделать, и он действительно работает, за исключением того, что, хотя основной сериализатор возвращает нужные мне поля, вложенный сериализатор возвращает обратно список primary_keys, которые связаны с первымтаблица через внешний ключ.Очевидно, мне нужны только поля "extra_field1", "extra_field2", но я не могу понять, где я ошибаюсь.Код ниже:

class SingleUseSerializer():

    def __init__(self, userdata, model, many=False, fields=None, exclude=None):
        if not fields and not exclude:
            cprint("SingleUseSerializer: fields and exclude are both None, can only have one.", "red")
        if fields and exclude:
            cprint("SingleUseSerializer: fields and exclude are both present, can only have one.", "red")
        self.main_serializer = {
            "model": model,
            "many": many,
            "fields": fields,
            "exclude": exclude
        }
        self.extra_serializers = {}
        self.userdata = userdata

    def load_extra_serializer(self, model, return_name, many=False, fields=None, exclude=None):
        self.extra_serializers[return_name] = {
            "model": model,
            "many": many,
            "fields": fields,
            "exclude": exclude
        }

    def checkout(self, query):

        def getSerializerClass(name):
            class A(serializers.ModelSerializer):
                def __init__(self, *args, **kwargs):
                    x = kwargs.get("fields", None)
                    if x:
                        self.Meta.fields = x
                        self.Meta.exclude = None
                        del kwargs["fields"]
                    y = kwargs.get("exclude", None)
                    if y:
                        self.Meta.exclude = y
                        self.Meta.fields = None
                        del kwargs["exclude"]
                    if not x and not y:
                        self.Meta.exclude = ('updated', 'created',)
                        self.Meta.fields = None
                    super(A, self).__init__(*args, **kwargs)
                class Meta:
                    model = None
            return type(name, (A,), {})

        main_serializer_class = getSerializerClass(name="MainSerializer")

        for k, v in self.extra_serializers.items():
            inner_serializer_class = getSerializerClass(name=str(k))
            inner_serializer_class.Meta.model = v["model"]
            inst = inner_serializer_class(many=True, fields=v["fields"])
            setattr(main_serializer_class, str(k), inst)
            self.main_serializer["fields"] += (str(k),)

        main_serializer_class.Meta.model = self.main_serializer["model"]
        x = main_serializer_class(query, context={"userdata": self.userdata}, fields=self.main_serializer["fields"])
        return x.data

Таким образом, мой вопрос заключается в том, как успешно вернуть обратно только выбранные поля на вложенных сериализаторах внутри созданных на лету сериализаторов, а не только значения pk.ПРИМЕЧАНИЕ: поля выбора для основного сериализатора работают и возвращают только те, которые мне нужны ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...