序列化器嵌套序列化器
規格表序列化器
class SKUSpecificationSerialzier(serializers.ModelSerializer): """ SKU規格表序列化器 """ spec_id = serializers.IntegerField() option_id = serializers.IntegerField() class Meta: model = SKUSpecification # SKUSpecification中sku外鍵關聯了SKU表 fields = ("spec_id", 'option_id')
商品表序列化器
class SKUSerializer(serializers.ModelSerializer):
#增加外鍵的字段 spu_id = serializers.IntegerField() category_id = serializers.IntegerField() spu = serializers.StringRelatedField(read_only=True) category = serializers.StringRelatedField(read_only=True)
#實現序列化器的嵌套
specs = SKUSpecificationSerialzier(many=True) class Meta: model=SKU fields='__all__'
重寫序列化器create和update方法
默認情況下,嵌套串行器是只讀的。如果要支持對嵌套序列化器字段的寫操作,則需要創建create()
和/或update()
方法,以明確指定應如何保存子關系。
def create(self, validated_data): # 獲取規格信息,並從validated_data數據中,刪除規格信息數據 specs_data = validated_data.pop('specs') # 保存sku sku = SKU.objects.create(**validated_data) # 對規格信息進行遍歷,來保存商品規格信息 for spec_data in specs_data: SKUSpecification.objects.create(sku=sku, **spec_data) # 返回sku return sku
def update(self, instance, validated_data): # 獲取規格信息,並從validated_data數據中,刪除規格信息數據 specs_data = validated_data.pop('specs') # 方案一: 調用父類 ,去實現沒有問題的數據更新 super().update(instance,validated_data) # 方案二 #獲取pk # pk = self.context['view'].kwargs.get('pk') # #更新數據 # SKU.objects.filter(id=pk).update(**validated_data) # 方案三 把父類的源碼 拿來 # for attr, value in validated_data.items(): # setattr(instance, attr, value) # instance.save() # 對規格信息進行遍歷,來保存商品規格信息 for spec_data in specs_data: # item {spec_id: "4", option_id: 8} SKUSpecification.objects.filter(sku=instance, spec_id=spec_data.get('spec_id')). \ update(option_id=spec_data.get('option_id')) return instance
使用事務保存數據
def create(self, validated_data): # 獲取規格信息,並從validated_data數據中,刪除規格信息數據 specs_data = validated_data.pop('specs') with transaction.atomic(): # 開啟事務 savepoint = transaction.savepoint() # 保存sku sku = SKU.objects.create(**validated_data) # 對規格信息進行遍歷,來保存商品規格信息 for spec_data in specs_data: SKUSpecification.objects.create(sku=sku, **spec_data) # 清除保存點 transaction.savepoint_commit(savepoint) # 返回sku return sku