代码之家  ›  专栏  ›  技术社区  ›  Руслан Прусаков

创建订单时,序列化程序的django-create方法,给出一个名为Country的错误Country已存在

  •  1
  • Руслан Прусаков  · 技术社区  · 1 年前

    我有一个订单模型,当在序列化程序的create方法中创建条目时,我试图将一个国家添加到many-many字段,但我得到了一个错误:一个名为country的国家已经存在

    我有模型:

    class Order(models.Model):
        name = models.CharField(max_length=150)
        description = models.TextField()
        price = models.DecimalField(max_digits=10, decimal_places=2, default=0, blank=True, null=True)
        created_at = models.DateTimeField(auto_now_add=True)
        period = models.DateField(_('Срок выполнения'), blank=True, null=True)
        specialization = models.ForeignKey(to='categories.Specialization', on_delete=models.PROTECT, related_name='order_specializations')
        country = models.ManyToManyField(Country, related_name='countries', blank=True)
        
        slug = models.SlugField(max_length=255)
        customer = models.ForeignKey(User,verbose_name=_("Заказчик"), on_delete=models.CASCADE, related_name='order_customers')
    
    
    class Country(models.Model):
        name = models.CharField(max_length=150, unique=True)
        phone_code = models.CharField(max_length=15, blank=True, null=True)
        flag = models.FileField(upload_to='flags/', null=True, blank=True)
        
        region = models.ForeignKey(Region, on_delete=models.PROTECT, related_name='countries')
        
    

    serializers.py

    class OrderCreateSerializer(serializers.ModelSerializer):
        specialization_id = serializers.IntegerField()
    
        class Meta:
            model = Order
            fields = ['id', 'name', 'description', 'price', 'created_at', 'specialization_id', 'slug', 'customer', 'file1', 'file2', 'file3', 'country']
            read_only_fields = ['customer', 'slug']
        
        country = CountryOrderSerializer(many=True)
        
        
        def create(self, validated_data):
            user = self.context['request'].user
            price = validated_data.get('price', 0)
            country_data = validated_data.pop('country', [])
            if check_customer_balance(customer=user, currency=currency, price=price):
                name = validated_data.get('name')
                specialization_id = validated_data.pop('specialization_id')
                validated_data['specialization'] = Specialization.objects.get(id=specialization_id)
                order = super().create(validated_data)
                create_order_transfer_money(user, currency, price, order)
            else:
                return Response({'error': 'Not enough funds'})
            for country_info in country_data:
                try:
                    country = Country.objects.get(**country_info)
                    order.country.add(country_info)
                except Country.DoesNotExist:
                    return Response({'error': 'Country does not exist'})
            return order
    

    当我发送邮件请求时

    {
        "name": "order3",
        "description": "ordeadadasd",
        "specialization_id": 1,
        "country": [{"name": "test"}]   
    }
    

    create方法甚至没有开始工作。我得到了一个错误:一个名为country的国家已经存在 在我看来,有人试图写入Country表,但它应该添加到与订单相关的表中。根本没有必要在Country表中写任何内容 请帮忙!)

    1 回复  |  直到 1 年前
        1
  •  0
  •   willeM_ Van Onsem    1 年前

    将子序列化程序标记为只读。序列化程序应该 构造响应,序列化程序构造 对象

    您还应该在验证器中进行验证,而不是创建方法:

    class OrderCreateSerializer(serializers.ModelSerializer):
        specialization_id = serializers.IntegerField()
    
        class Meta:
            model = Order
            fields = [
                'id',
                'name',
                'description',
                'price',
                'created_at',
                'specialization_id',
                'slug',
                'customer',
                'file1',
                'file2',
                'file3',
                'country',
            ]
            read_only_fields = ['customer', 'country', 'slug']
    
        country = CountryOrderSerializer(many=True, read_only=True)
    
        def validate(self, data):
            user = self.context['request'].user
            if not check_customer_balance(
                customer=user, currency=currency, price=data.get('price', 0)
            ):
                raise serializers.ValidationError('Not enough funds')
            country_data = self.initial_data.get('country', [])
            countries = Country.objects.get(
                name__in=[country['name'] for country in country_data]
            )
            if len(countries) != len(country_data):
                raise serializers.ValidationError('Invalid countries.')
            return data
    
        def create(self, validated_data):
            order = super().create(validated_data)
            create_order_transfer_money(user, currency, price, order)
            order.country.add(
                *Country.objects.filter(
                    name__in=[
                        country['name']
                        for country in self.initial_data('country', [])
                    ]
                )
            )
            return order