【问题标题】:Writable nested serializers with inherited django models具有继承 django 模型的可写嵌套序列化器
【发布时间】:2020-10-29 02:18:44
【问题描述】:

我正在努力使用我创建的可写嵌套序列化程序更新记录。

我正在创建的分类应用程序有许多 Listing 类别,每个类别都有一些独特的属性,但它们也共享许多属性。我有一些从父模型Listing 继承的 django 模型,其中一个模型 Battery 包含一些嵌套数据。到目前为止,我已经能够创建 Battery 记录,但是当我尝试更新它们时不断收到 AttributeErrors。

我已尝试仅包含相关代码。以下是我的看法:

# views.py

class ListingCreateView(CreateAPIView):
    queryset = Listing.objects.all()
    def get_serializer_class(self):
        category = self.request.data['category']
        if category == 1:
            return PercussionSerializer
         elif category == 6:
            return BatterySerializer

        return ListingSerializer

class ListingUpdateView(UpdateAPIView):
    queryset = Listing.objects.all()
    def get_serializer_class(self):
        category = self.request.data['category']
        if category == 1:
            return PercussionSerializer
        elif category == 6:
            return BatterySerializer

        return ListingSerializer

这是我的模型:

# models.py

## Parent model
class Listing(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, default=0.00)

## One of the child models
class Battery(Listing):
    model_name = models.TextField(blank=True, null=True, default="")
    color = models.ForeignKey(Color, on_delete=models.CASCADE, blank=True, null=True)
    manufacture_year = models.IntegerField(null=True)

## Model for the nested data in Battery model
class Drum(models.Model):
    drum_type = models.CharField(max_length=50, blank=True)
    size = models.TextField(blank=True, null=True, default="")
    battery = models.ForeignKey(Battery, related_name='drums', on_delete=models.CASCADE, null=True)

这是我的序列化程序:

# serializers.py

class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = '__all__'

class DrumSerializer(serializers.ModelSerializer):
    class Meta:
        model = Drum
        fields = ['drum_type', 'size', 'carrier', 'stand', 'cover', 'case', 'sold']

class BatterySerializer(serializers.ModelSerializer):
    drums = DrumSerializer(many=True)
    class Meta:
        model = Battery
        fields = ['id', 'title', 'description', 'price', 'model_name', 'color', 'manufacture_year', 'drums']

    def create(self, validated_data):
        drum_data = validated_data.pop('drums')
        battery = Battery.objects.create(**validated_data)
        for drum_data in drum_data:
            Drum.objects.create(battery=battery, **drum_data)
        return battery

    def update(self, instance, validated_data):
        # Update Listing field values
        instance.title = validated_data.get('title', instance.title)
        instance.description = validated_data.get('description', instance.description)
        instance.price = validated_data.get('price', instance.price)
        
        # Grab the Battery record for this Listing and update its values
        instance_battery = Battery.objects.get(pk=instance.pk)
        instance_battery.model_name = validated_data.get('model_name', instance_battery.model_name)
        instance_battery.color = validated_data.get('color', instance_battery.color)
        instance_battery.manufacture_year = validated_data.get('manufacture_year', instance_battery.manufacture_year)

        # Check for a list of drums
        drum_data = validated_data.pop('drums')
        # If it exists
        if drum_data:
            # Clear the existing drums
            instance_battery.drums.clear()
            # Create new drums
            Drum.objects.bulk_create(
                [
                    Drum(**drum)
                    for drum in drum_data
                ],
            )

        # Save the updated Listing & Battery
        instance.save()
        instance_battery.save()
        # Return the updated Battery
        return instance

我觉得我已经遵循了有关 writeable nested serializers correctly 的 DRF 文档,但是当我尝试将更新发布到 Battery 记录时,我仍然收到此 AttributeError:

AttributeError:尝试在序列化程序 BatterySerializer 上获取字段 drums 的值时出现 AttributeError。 序列化程序字段可能命名不正确,并且与 Listing 实例上的任何属性或键都不匹配。 原始异常文本为:“Listing”对象没有“drums”属性。

从错误消息来看,我认为 Django 模型继承需要 DRF 文档提供的更具体的解决方案。谁能帮我理解如何创建我需要的序列化程序来创建/更新从Listing 模型继承的Battery 记录,其中包含Drum 记录的嵌套列表?

谢谢!

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    我认为问题出现是因为视图等待列表实例。我可以提出以下建议:尝试重新定义def get_qyeryset(self)

    例如:

    class ListingUpdateView(UpdateAPIView):
        def get_queryset(self):
            if self.request.data['category'] == 6:
                return Battery.objects.all()
            else:
                return Listing.objects.all()
    
        def get_serializer_class(self):
            category = self.request.data['category']
            if category == 1:
                return PercussionSerializer
            elif category == 6:
                return BatterySerializer
    
            return ListingSerializer
    

    也许这不是最好的方法,但它可以解决你的问题

    【讨论】:

    • 我还没有时间彻底测试这个解决方案,但它似乎确实解决了这个问题。一旦我能够完全测试这一点并且事情似乎正在工作,我会将此答案标记为已接受。非常感谢!
    猜你喜欢
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2011-02-21
    • 2015-03-20
    • 1970-01-01
    相关资源
    最近更新 更多