[英]DRF: Post request with existing nested objects
我是Django Rest Framework和嵌套序列化程序的新手。 我有一個名為OrderSerialiser的ModelSerializer,其中包含兩個嵌套的ModelSerializer:ProductSerializer和ClientSerializer。
我希望在將發布請求發送到Order CreateAPI時創建模型客戶端和模型產品的新實例(僅當尚不存在這些實例時)。 我發現的解決方案是重寫OrderSerializer的create方法。
當沒有客戶端和產品具有相同電子郵件和sku的實例時,它可以正常工作,但返回錯誤,表明另一個實例中已經存在對象(具有相同電子郵件的客戶端和具有相同sku的產品)並沒有得到這些現有對象,我注意到在這種情況下未調用create方法,我認為我必須重寫serializers.is_valid()
方法,但是我沒有弄清楚應該怎么做。
models.py
class Client(models.Model):
email = models.EmailField(
verbose_name=_('Email address'),
max_length=255,
unique=True,
primary_key=True
)
first_name = models.CharField(_('first name'), max_length=30)
last_name = models.CharField(_('last name'), max_length=30)
class Product(models.Model):
sku = models.CharField(
verbose_name=_('SKU'),
unique=True,
max_length=120,
primary_key=True
)
name = models.CharField(
verbose_name=_('Name'),
max_length=150
)
url = models.URLField(
verbose_name=_('URL'),
blank=True,
null=True
)
class Order(models.Model):
client = models.ForeignKey(Client)
products = models.ManyToManyField(
Product,
related_name= "orders",
null=True,
blank=True,
)
serializers.py
class ProductSerialiser(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('sku', 'name', 'url')
class ClientSerialiser(serializers.ModelSerializer):
class Meta:
model = Client
fields = ('email','first_name', 'last_name')
class OrderSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
client = ClientSerialiser()
products = ProductSerialiser(many=True, required=False)
class Meta:
model = Order
fields = ('id', 'client', products')
def create(self, validated_data):
client_data = validated_data.pop('client')
try:
client_instance = Client.objects.get(email=client_data['email'])
except ObjectDoesNotExist:
client_instance = Client.objects.create(**client_data)
if 'products' in validated_data:
products_data = validated_data.pop('products')
order_instance = Order.objects.create(client=client_instance, **validated_data)
for product_data in products_data:
try :
product = Product.objects.get(sku=product_data['sku'])
except ObjectDoesNotExist:
product = Product.objects.create(**product_data)
product.orders.add(order_instance)
return order_instance
order_instance = Order.objects.create(client=client_instance, **validated_data)
return order_instance
赤目
我用來解決這類問題的一種方法基本上是在您的serializers.py內部,
def validate(self, data):
data = super(YourSerializer, self).validate(data)
try:
data['product'] = Product.objects.get(sku='bar')
except Product.DoesNotExist:
data['product'] = Product.object.create(sku='bar')
這並不理想,但是我確實找到了解決問題的解決方案(我正等待接受它作為答案,希望其他人可以做得更好)
我已經消除了ClientSerializer中的字段電子郵件和Productserializer中的字段sku的驗證器,然后手動檢查了對象的存在。
修改serialzers.py
class ProductSerialiser(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('sku', 'name', 'url')
extra_kwargs = {
'sku': {
'validators': []
}
}
class ClientSerialiser(serializers.ModelSerializer):
class Meta:
model = Client
fields = ('email', 'first_name', 'last_name')
extra_kwargs = {
'email': {
'validators': []
}
}
class OrderSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
client = ClientSerialiser(partial=True)
products = ProductSerialiser(many=True, required=False, partial=True)
class Meta:
model = Order
fields = ('id','client', products')
def create(self, validated_data):
client_data = validated_data.pop('client')
try:
print "**************** client exists ***********************"
client_instance = Client.objects.get(email=client_data['email'])
except ObjectDoesNotExist:
print "**************** creating a client ***********************"
client_instance = Client.objects.create(**client_data)
if 'products' in validated_data:
products_data = validated_data.pop('products')
order_instance = Order.objects.create(client=client_instance, **validated_data)
for product_data in products_data:
try :
print "**************** Product exists ***********************"
product = Product.objects.get(sku=product_data['sku'])
except ObjectDoesNotExist:
print "**************** creating object product ***********************"
product = Product.objects.create(**product_data)
product.orders.add(order_instance)
return order_instance
order_instance = Order.objects.create(client=client_instance, **validated_data)
return order_instance
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.