默认情况下,.create()方法不支持可写的嵌套字段。如何解决呢?

时间:2019-03-29 06:28:58

标签: django django-rest-framework django-serializer

关于在DRF中与中间模型进行多对多关系的序列化,我遇到了一个大问题:如果请求方法是get,那么一切都可以正常运行。但是,一旦我尝试将数据发布或放置到API中,就会出现以下错误:

  

内部服务器错误:/ api / ordering /追溯(最近一次调用)   最后):文件   “ /home/neha/.local/lib/python3.5/site-packages/django/core/handlers/exception.py”,   第34行,在内部       response = get_response(request)文件“ /home/neha/.local/lib/python3.5/site-packages/django/core/handlers/base.py”,   _get_response中的第126行       响应= self.process_exception_by_middleware(e,request)文件“ /home/neha/.local/lib/python3.5/site-packages/django/core/handlers/base.py”,   _get_response中的第124行       响应= wraped_callback(request,* callback_args,** callback_kwargs)文件“ /home/neha/.local/lib/python3.5/site-packages/django/views/decorators/csrf.py”,   第54行,在wrapped_view中       返回view_func(* args,** kwargs)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/viewsets.py”,   第116行,视线范围       返回self.dispatch(request,* args,** kwargs)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/views.py”,   495行,正在调度中       响应= self.handle_exception(exc)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/views.py”,   第455行,在handle_exception中       self.raise_uncaught_exception(exc)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/views.py”,   492行,正在派遣中       响应=处理程序(请求,* args,** kwargs)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/mixins.py”,   第21行,在create中       self.perform_create(serializer)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/mixins.py”,   第26行,在perform_create中       serializer.save()文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/serializers.py”,   第214行,保存       self.instance = self.create(validated_data)文件“ /home/neha/.local/lib/python3.5/site-packages/rest_framework/serializers.py”,   创建中的第929行       raise_errors_on_nested_writes('create',self,validated_data)文件   “ /home/neha/.local/lib/python3.5/site-packages/rest_framework/serializers.py”,   第823行,在raise_errors_on_nested_writes中       class_name = serializer。课程名称

     

AssertionError:.create()方法不支持可写   默认情况下嵌套字段。为以下内容编写明确的.create()方法   序列化器ordering.serializers.CustOrderSerializer,或设置   read_only=True在嵌套的序列化程序字段上。

views.py
from ordering.models import CustOrder, Product, Price, City, Area

from rest_framework import viewsets, permissions

from .serializers import CustOrderSerializer, ProductSerializer, 
PriceSerializer, CitySerializer, AreaSerializer

class CustOrderViewSet(viewsets.ModelViewSet):

    queryset = CustOrder.objects.all()

    permission_classes = [
        permissions.AllowAny
    ]

    serializer_class = CustOrderSerializer



class ProductViewSet(viewsets.ModelViewSet):

    queryset = Product.objects.all()

    permission_classes = [
        permissions.AllowAny
    ]


    serializer_class = ProductSerializer


class PriceViewSet(viewsets.ModelViewSet):

    queryset = Price.objects.all()

    permission_classes = [
        permissions.AllowAny
    ]

    serializer_class = PriceSerializer

class CityViewSet(viewsets.ModelViewSet):

    queryset = City.objects.all()

    permissions_classes = [
        permissions.AllowAny
    ]

    serializer_class = CitySerializer


class AreaViewSet(viewsets.ModelViewSet):

    queryset = Area.objects.all()

    permisions_classes = [
        permissions.AllowAny
    ]

    serializer_class = AreaSerializer 

    enter code here

 serializer.py

from rest_framework import serializers

from ordering.models import CustOrder, Area, City, Product, Price

class ProductSerializer(serializers.ModelSerializer):

    class Meta:
        model = Product
        fields = '__all__'

class PriceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Price
        fields = '__all__'

queryset=Product.objects.all())
# class AreaSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Area
#         fields = '__all__'

class CitySerializer(serializers.ModelSerializer):
    class Meta:
        model = City
        fields = '__all__'

class AreaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Area
        fields = '__all__'


class CustOrderSerializer(serializers.ModelSerializer):

    price = serializers.SlugRelatedField(slug_field='price',                                        queryset=Price.objects.all())
    # product = serializers.SlugRelatedField(slug_field='product', queryset=Product.objects.all())
    area = serializers.SlugRelatedField(slug_field='address', queryset=Area.objects.all())
    city = serializers.SlugRelatedField(slug_field='city', queryset=City.objects.all())
    product = ProductSerializer(many=True)
    class Meta:
        model = CustOrder
        fields = '__all__' 
    def create(self, validated_data):
        products = validated_data.pop('product')
        product = Product.objects.create(**validated_data) 
        for products in products:
            Product.objects.create(product=product, **products)
        return product

    # product = serializers.CharField(source="Product.product", read_only=True)
    # price = serializers.CharField(source="Price.price", read_only=True)
    # city = serializers.CharField(source="City.city", read_only=True)
    # area = serializers.CharField(source="Area.area", read_only=True)
    # price = serializers.SlugRelatedField(slug_field='price', queryset=Price.objects.all())
    # product = serializers.SlugRelatedField(slug_field='product', queryset=Product.objects.all())
    # area = serializers.SlugRelatedField(slug_field='address', queryset=Area.objects.all())
    # city = serializers.SlugRelatedField(slug_field='city', queryset=City.objects.all())
# def to_representation(self, instance):
#     response = super().to_representation(instance)
#     response['child'] = ProductSerializer(instance.product).data
#     return response  

    enter code here

model.py
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField
from django.contrib.postgres.fields import ArrayField
from phone_field import PhoneField
from django.contrib.gis.db import models
from decimal import Decimal
from django.db.models import Sum
class City(models.Model):
    city = models.CharField(max_length=200)

    def __str__(self):
        return self.city

    class Meta:
        verbose_name_plural = "Cities"


class Area(models.Model):
    city = models.ForeignKey('City', on_delete=models.CASCADE)
    address = models.CharField(max_length=200)


    def __str__(self):
        return self.address



class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    product = ArrayField(models.CharField(max_length=200, blank=True))
    # price = models.DecimalField(max_digits=50, decimal_places = 5, default=0)
    # def __str__(self):
    #     return str(self.product)+ ":$" + str(self.price)
    # @property
    # def price(self):
    #     return "$%s" % self.price
    def __str__(self):
        return str(self.product)

    # def __str__(self):
    #      return "%s" %  self.product_id
    # def natural_key(self):
    #     return self.product

    # class Meta:
    #     verbose_name_plural = "Products"

class Price(models.Model):
    # product = models.ManyToManyField(Product, through='CustOrder', through_fields=('price', 'product'),)
    # price_id = models.AutoField(primary_key=True)
    price = models.DecimalField(max_digits=50, decimal_places = 5, default=0)

    def __str__(self):
        return "%s" % self.price
        #  return str(self.product)+ ":$" +  str(self.price)



PRODUCT_CHOICES=(
     ('product_test_with_new_format','PRODUCT_TEST_WITH_NEW_FORMAT'),
     ('pulled chicken in pineapple relish','PULLED CHICKEN IN PINEAPPLE RELISH'),
     ('sundried sardines in mango relish', 'PULLED CHICKEN IN MANGO RELISH'),
     ('sundried sardines in mango relish','SUNDRIED SARDINES IN MANGO RELISH'),

)
GENDER_CHOICES = (
    ('male', 'MALE'),
    ('female', 'FEMALE'),
)
PAYMENT_CHOICES = (
    ('cod','COD'),
    ('card on delivery','CARD ON DELIVERY'),
    ('razor pay (netbanking)','RAZOR PAY (NET BANKING)'),
    ('razor pay (card)','RAZOR PAY (CARD)'),
    ('razor pay (wallet)','RAZOR PAY (WALLET)'),
    ('citrus','CITRUS'),
    ('paytm','PAYTM'),
)
CITY_CHOICES = (
    ('bangalore', 'BANGALORE'),
    ('hyderabad', 'HYDERABAD'),
    ('gurugram','GURUGRAM'),
    ('pune','PUNE'),
    ('chandigarh','CHANDIGARH'),
    ('mumbai','MUMBAI'),
)
# class ProductItem(models.Model):
# #     product = models.ManyToManyField(Price, through='CustOrder')
#     productitem = models.ManyToManyField(Product, through='CustOrder', through_fields=('productitem', 'product'),)
#     def __str__(self):
#         return str(self.productitem)

class CustOrder(models.Model):
    Customer_id = models.AutoField(primary_key=True)
    CustomerName = models.CharField(max_length=200)
    email = models.EmailField(max_length=70,blank=True, null= True, unique= True)
    gender = models.CharField(max_length=6, choices=GENDER_CHOICES)
    phone = PhoneField(null=False, blank=True, unique=True)
    landmark = models.PointField()
    #landmark = models.TextField(max_length=400, help_text="Enter the landmark", default='Enter landmark')
    houseno = models.IntegerField(default=0)
    #product_name = models.CharField(max_length=200, choices=PRODUCT_CHOICES,default='Boneless chicken')
    # product_id = models.ForeignKey(Product, on_delete=models.CASCADE,related_name='custorder_productid')

    product = models.ManyToManyField(Product, blank=True,related_name='pricetag')
    quantity = models.IntegerField(default=0)
    # price_id = models.ForeignKey(Price)
    price = models.ForeignKey(Price, on_delete=models.SET_NULL, null=True,related_name='pricetag')
    #price = models.DecimalField(max_digits=50, decimal_places=5, default=48.9)
    pay_method = models.CharField(max_length=200,choices=PAYMENT_CHOICES, default='RAZOR PAY')
    city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True) 
    area = models.ForeignKey(Area, on_delete=models.SET_NULL, null=True)
    Price.objects.aggregate(Sum('price'))
    def __str__(self):
         return self.CustomerName 


2 个答案:

答案 0 :(得分:0)

我认为您的错误与以下事实有关:您将返回Product对象而不是CustOrder对象?

答案 1 :(得分:0)

就像错误消息所言,您必须在序列化器上编写owm .create()方法,该方法负责在馈送的validated_data上创建对象。

这样做,您可以明确地告诉Django如何处理嵌套字段