Как настроить функцию to_internal_value в классе RelatedField для Django REST Framework? - PullRequest
1 голос
/ 03 февраля 2020

В моем коде мне нужно создать пользовательский класс RelatedField для нескольких ModelSerializer классов. Я следовал за этим ответом , он отлично работает. Но мне нужно сделать несколько RelatedField классов для каждой модели, которая у меня есть. Есть ли способ сделать только 1 RelatedField класс, чтобы его можно было использовать для всех связанных полей в моем ModelSerializer?
В настоящее время я делаю это так в serializers.py:

class ColorRelatedField(serializers.RelatedField):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        return ColorParent.objects.get(name=data)


class ProductCollectionRelatedField(serializers.RelatedField):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        return ProductCollection.objects.get(name=data)


class ProductSerializer(serializers.ModelSerializer):
    collection = ProductCollectionRelatedField(queryset=ProductCollection.objects.all(), many=False)
    color = ColorRelatedField(queryset=ColorParent.objects.all(), many=False)

    class Meta:
        model = Product
        fields = ['id', 'product_id', 'collection', 'color', 'video', 'status']

Как заставить to_internal_value функцию возвращать динамическую c модель в зависимости от того, кто вызывает метод:

class CustomRelatedField(serializers.RelatedField, model):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        return model.objects.get(name=data)


class ProductSerializer(serializers.ModelSerializer):
    collection = CustomRelatedField(model=ProductCollection, queryset=ProductCollection.objects.all(), many=False)
    color = CustomRelatedField(model=ColorParent, queryset=ColorParent.objects.all(), many=False)

    class Meta:
        model = Product
        fields = ['id', 'product_id', 'collection', 'color', 'video', 'status']

Когда я пытался добавить параметр model в класс CustomRelatedField, сообщение об ошибке У меня было:

имя model не определено.

Ответы [ 2 ]

3 голосов
/ 03 февраля 2020

Вам не нужно передавать model в качестве аргумента CustomRelatedField, потому что вы уже передаете набор запросов. Просто удалите атрибут model и получите модель из набора запросов следующим образом:

 def to_internal_value(self, data):
     model = self.queryset.model
     return model.objects.get(name=data)
2 голосов
/ 03 февраля 2020

Попробуйте переопределить __init__() метод следующим образом:

class CustomRelatedField(serializers.RelatedField):
    def __init__(self, *args, **kwargs):
        self.model = kwargs.pop("model")
        super().__init__(*args, **kwargs)

    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        return self.model.objects.get(name=data)

Примечание self.model вместо model ins to_internal_value(). Теперь вы можете передать модель с аргументами поля:

class ProductSerializer(serializers.ModelSerializer):
    collection = CustomRelatedField(model=ProductCollection, queryset=ProductCollection.objects.all(), many=False)
    color = CustomRelatedField(model=ColorParent, queryset=ColorParent.objects.all(), many=False)
...