Rest Framework десериализует одно поле и сериализует объект модели - PullRequest
0 голосов
/ 17 февраля 2020

Привет, я хочу десериализовать только используя 1 поле. Однако я хочу сериализовать его как объект в зависимости от модели.

Предположим, у меня есть:

#models.py
class Product(models.Model):
    name = models.CharField()
    amount = models.IntegerField()
    description = models.TextField()

class Query(models.Model):
    name = models.CharField()
    product = models.ForeignKey(Product)
    ...

#serializers.py
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

class QuerySerializer(serializers.ModelSerializer):
    product = ProductSerializer()

    class Meta:
        model = Query
        fields = '__all__'

Я хочу POST / десериализовать что-то подобное на QuerySerializer:

{
    "name": "Query 1",
    "product": "Banana",
    ...
}

и я хочу что-то подобное взамен сериализатора:

{
    "name": "Query 1",
    "product": {
                   "name": "Banana",
                   "amount": 1,
                   "description": "Banana description"
               }
    ...
}

Я знаю, что способ переопределяет to_internal_value, но мне это не нравится, поскольку он портится с ошибками ValidationErrrors.

Я также получаю это в результате:

{'product': {'non_field_errors': 
['Invalid data. Expected a dictionary, but got str.']}}

1 Ответ

1 голос
/ 17 февраля 2020

Прежде всего, сделайте поле name равным Product как unique, чтобы избежать ненужных осложнений.

class Product(models.Model):
    name = models.CharField(<b>unique=True</b>)
    amount = models.IntegerField()
    description = models.TextField()

и измените ваш сериализатор на

class QuerySerializer(serializers.ModelSerializer):
    <b>product = serializers.CharField(write_only=True)</b>

    class Meta:
        model = Query
        fields = '__all__'

    <b>def create(self, validated_data):
        product_name = validated_data.pop('product')
        product_instance = Product.objects.get(name=product_name)
        return Query.objects.create(product=product_instance, **validated_data)

    def to_representation(self, instance):
        rep = super().to_representation(instance)
        rep['product'] = ProductSerializer(instance.product).data
        return rep</b>

Ссылка: DRF: простое назначение внешнего ключа с вложенными сериализаторами?

...