Django Rest Framework:尝试在序列化程序`OrderCreateSerializer`

时间:2017-11-17 06:35:38

标签: python django django-rest-framework

这是我的模特:

class Order(models.Model):
    """
    订单
    """
    order_num = models.CharField(max_length=128, unique=True)  # 订单编号
    order_status = models.CharField(max_length=12)  # 订单状态  "未支付", "已支付,未完成", "已完成", "已经删除","其他"
    product_describe = models.TextField()  # 产品描述
    billing_type = models.CharField(max_length=16)  # 计费类型
    buytime = models.CharField(max_length=16)  # 比如:1月  永久
    count = models.IntegerField()  # 购买数量
    paytype = models.CharField(max_length=16)  # 支付方式(支付包,微信,xxx)
    cost = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)  # 费用(需要花费多少钱)
    account = models.ForeignKey(to=Account) # 所属账户

    ctime = models.DateTimeField(auto_now_add=True)  # 创建时间
    uptime = models.DateTimeField(auto_now=True)  # 更新时间

    def __str__(self):
        return self.product_describe
    def __unicode__(self):
        return self.product_describe

这是我的序列化器:

class OrderCreateSerializer(ModelSerializer):

    data_params = serializers.DictField()  # 根据产品数据模型不同而异

    class Meta:
        model = Order
        fields = (
            "product_describe",  # 产品描述 (购买xx产品 + 参数)
            "billing_type", # 计费类型 ("包年包月")
            # "buytime", # "购买时间"
            # "count", # 数量
            # "paytype", # 支付方式
            "data_params",  # 数据
        )
    def create(self, validated_data):

        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user

        validated_data["order_num"] = generateOrderNum(userid=user.id)
        validated_data["order_status"] = "未支付"

        data_dic = validated_data.pop("data_params") #

        validated_data["buytime"] = data_dic["data"]["buytime"]
        validated_data["count"] = data_dic["data"]["count"]
        validated_data["paytype"] = ""  # 支付类型

        validated_data["cost"] = 0.00  # 所需钱
        validated_data["account"] = user.account  # 是哪个账户

        return Order.objects.create(**validated_data)

你知道,在我的序列化程序中,我弹出了data_params

data_dic = validated_data.pop("data_params") 

但是当我访问此API时,我得到:

  

/ api / financialmanage / order / add /
的AttributeError   尝试在序列化程序data_params上获取字段OrderCreateSerializer的值时出现AttributeError   序列化程序字段可能名称不正确,并且与Order实例上的任何属性或键都不匹配   原始例外文字是:'订单'对象没有属性' data_params'。

如果我不弹出data_params,我会收到以下错误:

  

/ api / financialmanage / order / add /
的TypeError   ' data_params'是此函数的无效关键字参数

修改

我的views.py:

class OrderSerializerCreateAPIView(CreateAPIView):
    """
    create Order
    """
    serializer_class = OrderCreateSerializer
    permission_classes = []
    queryset = Order.objects.all()

修改-2

就我而言,data_params词典对我来说是必要的。 因为当我购买具有计数,vcpus,ram,磁盘和带宽的产品(例如CloudServer)时,我通过data_params来获取它。

您可能想知道为什么我必须使用data_params来接收数据,因为产品可能不同,如果产品是Wine,它现在不能拥有vcpus属性。

3 个答案:

答案 0 :(得分:0)

class OrderCreateSerializer(ModelSerializer):
    data_params = DictField(child=serializers.CharField())
    .
    .
    .
    def create(self, validated_data):
        print(validated_data)

        data_dic = validated_data.pop("data_params")
        print(data_dic)
        return super(OrderCreateSerializer, self).create(validated_data)


class OrderSerializer(ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

    # by @Vasil Shtiliyanov if you want return data_parms after create
    def to_representation(self, instance):
        serialized_data = super(OrderSerializer, self).to_representation(instance)
        serialized_data['data-params'] = #logic goes here
        return serialized_data

class OrderSerializerCreateAPIView(CreateAPIView):
    """
    create Order
    """
    serializer_class = OrderCreateSerializer
    permission_classes = []
    queryset = Order.objects.all()

   def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        instance = self.perform_create(serializer)
        data = OrderSerializer(instance).data
        headers = self.get_success_headers(data )
        return Response(data , status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
       return serializer.save()

答案 1 :(得分:0)

如果要在序列化程序不是模型中的字段时将data-params参数添加到序列化程序,则应使用DRF的def to_representation函数。应该看起来像这样:

def to_representation(self, instance):
serialized_data = super(SerializerClass, self).to_representation(instance)
serialized_data['data-params'] = #logic goes here
return serialized_data

从Meta类的fields参数中删除data-params。

答案 2 :(得分:0)

我对您的解决相同:

data_params = serializers.DictField()   # yours

data_params = serializers.DictField(write_only=True)  # try it, pls. 

源代码:

# rest_framework/serializers.py => L504
def to_representation():.
    ..  
    fields = self._readable_fields  # this function rest_framework/serializers.py=>L371
    ...