简体   繁体   中英

how to create multiple objects with one request DRF

I have the following models

class Product(models.Model):
    name = models.CharField(null=True, blank=True, max_length=500)
    category = models.CharField(null=True, blank=True, max_length=120)


class SpecificationName(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True, related_name='specifications')
    name = models.CharField(max_length=125)

class Attribute(models.Model):
    spec_name = models.ForeignKey(SpecificationName, on_delete=models.CASCADE, null=True, related_name='attributes')
    index = models.CharField(max_length=200, blank=True, null=True)
    value = models.CharField(max_length=250, blank=True, null=True)

after saving objects in Django admin I have an example

{
    "name": "Apple Smart Watch",
    "category": "IT",
    "specifications": [
        {
            "name": "Test Data",
            "attributes": [
                {
                    "index": "test",
                    "value": "test2"
                },
                {
                    "index": "test7",
                    "value": "test8"
                },
                {
                    "index": "test9",
                    "value": "test10"
                }
            ]
        },
        {
            "name": "Test Data Continued",
            "attributes": [
                {
                    "index": "bla",
                    "value": "bla1"
                },
                {
                    "index": "bla 2",
                    "value": "bla 4"
                },
                {
                    "index": "test9",
                    "value": "test10"
                }
            ]
        },
        {
            "name": "Test Spec",
            "attributes": []
        }
    ]
}

I need to save this kind of object with one request but I am failing to do this

my serializer looks like this

class ProductSerializer(serializers.ModelSerializer):
    specifications = SpecNameSerializer(many=True)
    # attributes = AttributeSerializer(many=True, required=False)

class Meta:
    model = Product
    fields = ['name', 'category', 'brand', 'price', 'specifications']

def create(self, validated_data):
    specs = validated_data.pop('specifications')
    instance = Product.objects.create(**validated_data)

    for spec in specs:
        SpecificationName.objects.create(product=instance, **spec)
        print(spec)

    return instance

with this code, I am getting the following result but not as expected

{
    "name": "Appel watch series",
    "specifications": [
        {
            "name": "Test Data",
            "attributes": []
        },
        {
            "name": "Test Data comn",
            "attributes": []
        },
        {
            "name": "Test Spec",
            "attributes": []
        }
    ]
}

it cannot write into attributes

I searched for many answers but I did not find or applied some of them, again it did not help me. I am using just ListCreateView in the views. Please is there anybody who can help solve this problem. Thanks in advance!

SOLVED

I am using here ModelSerializer instead I used Serializer and added some changes here my answer and it worked

class AttributeSerializer(serializers.Serializer):
    index = serializers.CharField(max_length=200)
    value = serializers.CharField(max_length=200)


class SpecNameSerializer(serializers.ModelSerializer):
    attributes = AttributeSerializer(many=True)

    class Meta:
        model = SpecificationName
        fields = '__all__'


class ProductSerializer(serializers.ModelSerializer):
    specifications = SpecNameSerializer(many=True)


    class Meta:
        model = Product
        fields = ['name', 'category', 'brand', 'price', 'specifications']


    def create(self, validated_data):
        specs = validated_data.pop('specifications')
        instance = Product.objects.create(**validated_data)

        for spec in specs:
            SpecificationName.objects.create(product=instance, **spec)
            attrs = spec.pop('attributes')
            for attr in attrs:
                Attribute.objects.create(spec_name=spec, **attr)

        return instance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM