Django 如何在保存模型实例时保证嵌套对象的原子性?
这是我的密码:Django 如何在保存模型实例时保证嵌套对象的原子性?,django,validation,django-rest-framework,Django,Validation,Django Rest Framework,这是我的密码: from django.db import models class Car(models.Model): is_crawler = models.BooleanField() class Wheel(models.Model): car = models.ForeignKey(A, related_name='wheels', on_delete=models.CASCADE) radius = models.IntegerField() cl
from django.db import models
class Car(models.Model):
is_crawler = models.BooleanField()
class Wheel(models.Model):
car = models.ForeignKey(A, related_name='wheels', on_delete=models.CASCADE)
radius = models.IntegerField()
class WheelSerializer(serializer.ModelSerializer):
class Meta:
model = Wheel
fields = '__all__'
class CarSerializer(serializers.ModelSerializer):
wheels = WheelSerializer(many=True)
class Meta:
model = Car
fields = '__all__'
def validate(self, attrs):
is_crawler = attrs.get('is_crawler')
wheels_data = attrs.get('wheels')
if wheels_data and is_crawler:
raise ValidationError("Crawler can't have wheels")
def create(self, validated_data):
is_crawler = attrs.get('is_crawler')
wheels_data = attrs.get('wheels')
car = Car.objects.create(**validated_data)
for wheel_data in wheels_data:
wheel_serializer = WheelSerializer(**wheel_data)
if wheel_serializer.is_valid():
wheel_serializer.save()
return car
所以,当我试图发送类似
{“is_crawler”:true,“wheels”:[{“radius”:5}]}
对于CarSerializer,它将引发ValidationError,从而从视图中引发400响应
但它并不禁止在admin中为爬虫程序创建轮子。是否有一种方法可以将验证从序列化程序转移到模型的
clean
或save
方法,以禁止创建带轮子的履带车或在代码的任何部分向履带车添加轮子?如果有,它会在DRF中引发相同的ValidationError并从DRF返回HTTP_400吗?您可以向模型中添加clean
方法,但不会在序列化程序中调用它。这是为了分离关注点,如中所述
这是您在汽车
和车轮
上使用清洁方法的代码,并对其进行了一些小的更改,以使其在我这边工作
等级车(型号.型号):
is_crawler=models.BooleanField()
def清洁(自清洁):
如果self.is_爬虫和self.wheels.count():
raise ValidationError(“爬虫程序不能有轮子”)
类车轮(型号.型号):
car=车型.ForeignKey(汽车,相关的_name=“车轮”,在_delete=车型.CASCADE上)
radius=models.IntegerField()
def清洁(自清洁):
如果self.car.is_爬虫:
raise ValidationError(“爬虫程序不能有轮子”)
类序列化程序(serializers.ModelSerializer):
类元:
型号=车轮
fields=“\uuuu all\uuuuuu”
只读字段=(“汽车”)
类CarSerializer(serializers.ModelSerializer):
wheels=WheelSerializer(多个=真)
类元:
型号=汽车
fields=“\uuuu all\uuuuuu”
def验证(自身、属性):
is\u crawler=attrs.get(“is\u crawler”)
wheels\u data=attrs.get(“车轮”)
如果是数据,并且是爬虫程序:
raise ValidationError(“爬虫程序不能有轮子”)
返回属性
def创建(自我验证的_数据):
wheels\u data=已验证的\u data.pop(“wheels”)
car=car.objects.create(**已验证的_数据)
对于wheels_数据中的wheels_数据:
车轮=车轮。对象。创建(**wheel\u数据,汽车=汽车)
汽车.车轮.添加(车轮)
回程车
正如文档中所说的,您还可以在序列化程序的验证方法中实例化您的模型,但不鼓励这样做
def验证(自身、属性):
实例=示例模型(**attrs)
instance.clean()
返回属性