【问题标题】:Reuse Existing Object in Django Rest Framework Nested Serializer在 Django Rest Framework 嵌套序列化程序中重用现有对象
【发布时间】:2014-12-02 12:58:07
【问题描述】:

在 drf 中使用嵌套序列化器时如何重新使用引用的对象:

假设我有以下两个Models:

class Address(models.Model):
    address_line = models.CharField(max_length=45)

class Person(models.Model):
    name = models.CharField(max_length=45)
    address = models.ForeignKey(Address)

Serializers:

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address

class PersonSerializer(serializers.ModelSerializer):
    address = AddressSerializer()

    class Meta:
        model = Person

现在,序列化程序处理同时创建AddressPerson。例如,当我发布以下内容时:

{
    'name': 'Alex',
    'address': {
        'address_line': "1 Here"
    }
}

创建了一个Person,并创建了一个Address,其中Person 指向新创建的Address

如果已经存在具有给定address_lineAddress,那么不创建新Address 而是重用现有Address 的最佳方法是什么?即,如果我想将address_line 字段设为unique? (这种对象重用有时称为“实习”)

如果有两个地址字段address_line1address_line2,并且我想重用Address 对象,如果这两个字段都已经存在Address(即unique_together=(address_line1, address_line2))?

p>

【问题讨论】:

  • 我遇到了同样的问题。你找到解决办法了吗?

标签: django django-models django-rest-framework


【解决方案1】:

我发现通过覆盖序列化器的create 方法,代码可能更简单唯一字段:

models.py

class Tag(models.Model):
    # more fields...

    tag = models.CharField(max_length=45, unique=True)

    def __str__(self):
        return self.tag

    
class Scenery(models.Model):
    # more fields...

    tags = models.ManyToManyField(to=Tag, related_name='tagged_sceneries', blank=True)

serializers.py

from django.core.exceptions import ObjectDoesNotExist
from rest_framework.serializers import ModelSerializer
from drf_writable_nested.serializers import WritableNestedModelSerializer
from drf_writable_nested.mixins import UniqueFieldsMixin
from .models import Tag, Scenery

class TagSerializer(UniqueFieldsMixin, ModelSerializer):
    class Meta:
        model = Tag
        fields = ['tag']

    def create(self, validated_data):
        try:
            # if there is already an instance in the database with the
            # given value (e.g. tag='apple'), we simply return this instance
            return Tag.objects.get(tag=validated_data['tag'])
        except ObjectDoesNotExist:
            # else, we create a new tag with the given value
            return super(TagSerializer, self).create(validated_data)


class ScenerySerializer(WritableNestedModelSerializer):
    # Many to many + unique
    tags = TagSerializer(many=True)

    class Meta:
        model = Scenery
        fields = [
            'tags',
            # ... more fields
        ]

【讨论】:

  • 虽然这需要包drf-writable-nested 这应该肯定是正确的答案。有了这个,我毫不费力地做了大量的工作。
【解决方案2】:

最近遇到一个类似的问题,用下面的方法解决了(代码未经测试,仅供参考):

class PersonSerializer(serializers.ModelSerializer):
    address = AddressSerializer()

    class Meta:
        model = Person

    def create(self, validated_data):
        # pop the validated user data
        # assuming its a required field,
        # it will always be there in validated_data
        address = validated_data.pop('address')

        try:
            address = Address.objects.get(address_line=address.get('address_line'))
        except ObjectDoesNotExist:
            address_serializer = AddressSerializer(data=address)
            address_serializer.is_valid(raise_exception=True)
            address = address_serializer.save()
        else:
            # save the user and update the validated_data for setting up profile
            validated_data['address'] = address

        return super(PersonSerializer, self).create(validated_data)

希望这会有所帮助:)

【讨论】:

  • 我遇到了同样的问题,可以通过结合您的答案来解决它具有此[某些字段]的[父对象类型]已经存在。.
猜你喜欢
  • 2015-12-16
  • 2018-05-20
  • 2015-11-14
  • 2021-11-30
  • 2014-07-07
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多