我有两个模型Product
和Variant
如下
models.py
class Product(models.Model):
GENDER = [
('M', 'male'),
('F', 'female'),
('U', 'unisex'),
]
store = models.ForeignKey(
Store, on_delete=models.CASCADE, related_name='products')
name = models.CharField(max_length=80)
slug = models.SlugField(max_length=200, unique=True, blank=True, null=True)
description = models.TextField()
brand = models.CharField(max_length=200, blank=True, null=True)
model = models.CharField(max_length=200, blank=True, null=True)
gender = models.CharField(max_length=20, choices=GENDER)
image_1 = models.URLField()
image_2 = models.URLField()
category = models.ForeignKey(
'Category', related_name="products", on_delete=models.CASCADE, null=True, blank=True)
return_policy = models.IntegerField(null=True, blank=True)
in_warehouse = models.BooleanField(default=False)
is_approved = models.BooleanField(default=False)
is_rejected = models.BooleanField(default=False)
is_disabled = models.BooleanField(default=False)
is_deleted = models.BooleanField(default=True)
score = models.IntegerField(default=0)
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.name
class Variant(models.Model):
COLORS = [
('black', 'Black'),
('grey', 'Grey'),
('white', 'White'),
('blue', 'Blue'),
('green', 'Green'),
('yellow', 'Yellow'),
('orange', 'Orange'),
('red', 'Red'),
('purple', 'Purple'),
('gold', 'Gold'),
('silver', 'Silver'),
('brown', 'Brown'),
('pink', 'Pink'),
('colorless', 'Colorless'),
('multi-colored', 'Multi Colored'),
]
SIZES = [
('xxs', 'XXS'),
('xs', 'XS'),
('s', 'S'),
('m', 'M'),
('l', 'L'),
('xl', 'XL'),
('xxl', 'XXL'),
('xxxl', 'XXXL')
]
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name="variants", null=True, blank=True)
is_default = models.BooleanField(default=False)
price = models.FloatField()
old_price = models.FloatField(blank=True, null=True)
quantity = models.IntegerField()
size = models.CharField(
max_length=20, choices=SIZES, null=True, blank=True)
shoe_size = models.IntegerField(null=True, blank=True)
color = models.CharField(max_length=20, choices=COLORS)
image = models.URLField()
is_deleted = models.BooleanField(default=True)
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.product.name + " variant"
我想创建一个产品,同时传递variants
列表,以便它可以自动创建产品的变体,如下所示
serializer.py
class VariantSerializer(serializers.ModelSerializer):
image = serializers.ImageField()
class Meta:
model = Variant
fields = ['product', 'is_default', 'price',
'old_price', 'quantity', 'size', 'shoe_size', 'color', 'image']
class ProductSerializer(serializers.ModelSerializer):
variants = VariantSerializer(many=True)
image_1 = serializers.ImageField()
image_2 = serializers.ImageField()
class Meta:
model = Product
fields = ['store', 'name', 'description', 'brand',
'model', 'gender', 'image_1', 'image_2', 'category']
def validate_category(self, value):
if not Category.objects.filter(slug=value).exists():
raise serializers.ValidationError(
{'category': 'category does not exist!'})
def validate_variants(self, value):
if len(value) > 5:
raise serializers.ValidationError(
"Maximum of 5 serializers per product")
return value
def validate_store(self, value):
request = self.context.get('request')
if not Store.objects.filter(id=value, user=request.user).exists():
raise serializers.ValidationError(
{'store': 'Store does not exist!'})
def create(self, validated_data):
name = validated_data.get("name")
store = validated_data.get("store")
image_1 = validated_data.pop("image_1")
image_2 = validated_data.pop("image_2")
variants = validated_data.pop("variants")
category = validated_data.pop("category")
product = Product(**validated_data)
product.save()
# Handle category
category = get_object_or_404(Category, slug=category)
product.category.set(category)
# Handle Slug
slug = slugify(name) + '-' + str(product.id)
product.slug = slug
# Handle Variant
for variant in variants:
variant["product"] = product.id
new_variant = VariantSerializer(data=variant)
if new_variant.is_valid():
image = variant.pop("image")
new_variant.image = None
new_variant.save()
try:
image_data = cloudinary.uploader.upload(image,
public_id=f'jetronmall/{settings.CLOUD_FOLDER_NAME}/stores/{store.id}/products/{product.id}/variants/{new_variant.id}',
crop='fill',
width='500',
height='500',
format='webp')
image = image_data.get("secure_url")
new_variant.image = image
new_variant.save()
except:
product.delete()
raise serializers.ValidationError(
{"image": "cloudinary failed to upload"})
else:
product.delete()
raise serializers.ValidationError(
{"variants": new_variant.errors})
# Handle Image
try:
image_1_data = cloudinary.uploader.upload(image_1,
public_id=f'jetronmall/{settings.CLOUD_FOLDER_NAME}/stores/{store.id}/products/{product.id}/1',
crop='fill',
width='500',
height='500',
format='webp')
image_1 = image_1_data.get("secure_url")
product.image_1 = image_1
image_2_data = cloudinary.uploader.upload(image_1,
public_id=f'jetronmall/{settings.CLOUD_FOLDER_NAME}/stores/{store.id}/products/{product.id}/2',
crop='fill',
width='500',
height='500',
format='webp')
image_2 = image_2_data.get("secure_url")
product.image_2 = image_2
product.is_deleted = False
product.save()
except:
product.delete()
raise serializers.ValidationError(
{"images": "cloudinary failed to upload"})
return product
我试图POST的数据是
{
"name": "first product",
"category": "tops",
"brand": "first",
"model": "test",
"description": "someone is the ehd kdvk kja avm elgm klrm gkrlng lkrgn rgn ognr bonr btklbn lbknb klnb rkngrkla rkgnrkgrng",
"image_1": File,
"image_2": File,
"gender": "U",
"variants": [
{
"price": "23000",
"quantity": "4",
"image": File,
"size": "m",
"shoe_size": "4",
"color": "black",
"is_default": true
},
{
"price": "44",
"quantity": "44",
"image": File,
"size": "m",
"shoe_size": "44",
"color": "black",
"is_default": false
},
{
"price": "22222",
"quantity": "22",
"image": File,
"size": "m",
"shoe_size": "22",
"color": "black",
"is_default": false
}
]
}
但它扔给我一个415 Unsupported Media Type
{"detail":"Unsupported media type "application/json;charset=UTF-8" in request."}
那么我该如何使用嵌套序列化器来实现这个逻辑呢?
我已经解决了这个问题,我只需要添加标题headers: { "Content-Type": "multipart/form-data" },