Django Rest Framework, как добавить поле сериализатора из списка имен - PullRequest
0 голосов
/ 23 октября 2018

У меня есть сериализатор Django Rest Framework, который содержит много полей с плавающей точкой, например,

class MySerializer(serializers.Serializer):
    unitID = serializers.CharField(required=True, allow_blank=False, max_length=50)
    timestamp = serializers.DateTimeField(required=True)
    VonDC = serializers.FloatField(required=False)
    VonAC = serializers.FloatField(required=False)
    VoffDC = serializers.FloatField(required=False)
    VonDC2 = serializers.FloatField(required=False)
    etc...

Я хотел бы иметь возможность создавать эти поля из списка имен полей, например,

the_fields = ['VonDC', 'VonAC', 'VoffDC', 'VonDC2', etc...] 

class MySerializer(serializers.Serializer):
    unitID = serializers.CharField(required=True, allow_blank=False, max_length=50)
    timestamp = serializers.DateTimeField(required=True)

    for f in the_fields:
        <something>[f] = serializers.FloatField(required=False)
        or
        <some_function>(<something>, f, serializers.FloatField(required=False) )

Я не смог найти, что "что-то" или "some_function" в вышеприведенном было бы.

Возможно ли это сделать?Есть ли в Python способ добавить атрибуты в класс и взять имя из переменной?Или есть конкретная поддержка для этого в Django Rest Framework?

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

(Список полей по существу фиксирован, его изменение может повлиять на всю систему. Время от времени он может изменяться, но он, безусловно, не изменится во время работы программы)

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Я думаю, что «обычно» следующий код сделает работу по добавлению FloatFields в качестве атрибутов класса.

Обратите внимание, что цикл for находится после класса, а не в его теле.

the_fields = ['VonDC', 'VonAC', 'VoffDC', 'VonDC2', etc...] 

class MySerializer(serializers.Serializer):
    unitID = serializers.CharField(required=True, allow_blank=False, max_length=50)
    timestamp = serializers.DateTimeField(required=True)

for name in meas_names:
    setattr(MySerializer, name, serializers.FloatField(required=False))

Однако serializers.Serializer имеет метакласс, который включает специальную обработку любых присутствующих атрибутов «Field».в теле класса.FloatFields, которые добавляются циклом for, добавляются после того, как метакласс выполнил свою работу, поэтому не обрабатываются правильно.

Метакласс удаляет все найденные атрибуты «Field» и перемещает их в диктовку _declared_fields.

Похоже, мы можем добавить поля в класс, добавив их непосредственно в _объявленные поля.

the_fields = ['VonDC', 'VonAC', 'VoffDC', 'VonDC2', etc...] 

class MySerializer(serializers.Serializer):
    unitID = serializers.CharField(required=True, allow_blank=False, max_length=50)
    timestamp = serializers.DateTimeField(required=True)

for name in meas_names:
    MySerializer._declared_fields[name] = serializers.FloatField(required=False)
0 голосов
/ 23 октября 2018

попробуйте переопределить метод сериализатора __init__(), как показано ниже,

the_fields = ['VonDC', 'VonAC', 'VoffDC', 'VonDC2', ]


class MySerializer(serializers.Serializer):
    unitID = serializers.CharField(required=True, allow_blank=False, max_length=50)
    timestamp = serializers.DateTimeField(required=True)

    <b>def __init__(self, *args, **kwargs):
        super(MySerializer, self).__init__(*args, **kwargs)
        for field in the_fields:
            self.fields.update({field: serializers.FloatField(required=False)})</b>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...