【问题标题】:DRF post request multiple inner serializersDRF post请求多个内部序列化器
【发布时间】:2018-12-08 11:56:41
【问题描述】:

我有三个模型,分别命名为 Smoker、Switch、Survey 我在 Switch 模型中将 Smoker 作为外键,在 Survey 模型中将 switch 作为外键

class Smoker(models.Model):
    first_name = models.CharField(max_length=50, blank=True, null=True)
    last_name = models.CharField(max_length=50, blank=True, null=True)
    mobile = models.IntegerField(null=True, blank=True)
    gender = models.BooleanField(blank=True, null=True)
    age = models.ForeignKey(Age,models.DO_NOTHING,blank=True, null=True)
    occupation = models.ForeignKey(Occupation, models.DO_NOTHING, blank=True, null=True)

class Switch(models.Model):
    time = models.TimeField(blank=True, null=True)
    count_outers = models.IntegerField(blank=True, null=True)
    count_packs = models.IntegerField(blank=True, null=True)
    smoker = models.ForeignKey(Smoker, models.DO_NOTHING, blank=True, null=True)
    new_brand = models.ForeignKey(NewBrand, models.DO_NOTHING, blank=True, null=True)
    new_sku = models.ForeignKey(NewSku, models.DO_NOTHING, blank=True, null=True)

    # def __str__(self):
    #     return self.time.strftime("%H:%M")


class Survey(models.Model):
    user = models.ForeignKey(User, models.DO_NOTHING, blank=True, null=True)
    date = models.DateField(null=True, blank=True)
    bool_switch = models.BooleanField(null=True, blank=True)
    reason = models.ForeignKey(Reason, models.DO_NOTHING, null=True, blank=True)
    shift = models.ForeignKey(ShiftingTime, models.DO_NOTHING, null=True, blank=True)
    current_brand = models.ForeignKey(CurrentBrand, models.DO_NOTHING, null=True, blank=True)
    current_sku = models.ForeignKey(CurrentSku, models.DO_NOTHING, null=True, blank=True)
    pos = models.ForeignKey(Pos, models.DO_NOTHING, null=True, blank=True)
    switch = models.ForeignKey(Switch, models.DO_NOTHING, null=True, blank=True)

这里有我的序列化程序:

class SmokerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Smoker
        fields = '__all__'

class SwitchSerializer(serializers.ModelSerializer):
    smoker = SmokerSerializer()
    class Meta:
        model = Switch
        fields = '__all__'
        def create(self, validated_data):
           smoker_data = validated_data.pop('smoker', None)
           if smoker_data:
             smoker = Smoker.objects.create(**smoker_data)
             validated_data['smoker'] = smoker
           return Switch.objects.create(**validated_data)

class SurveySerializer(serializers.ModelSerializer):
    switch = SwitchSerializer()

    class Meta:
        model = Survey
        fields = '__all__'
    def create(self, validated_data):

        switch_data = validated_data.pop('switch', None)
        if switch_data:
            switch = Switch.objects.create(**switch_data)
            validated_data['switch'] = switch
        return Survey.objects.create(**validated_data)

我为创建和列出所有调查做了一个通用

class SurveyCreateAPIView(generics.ListCreateAPIView):
    def get_queryset(self):
        return Survey.objects.all()
    serializer_class = SurveySerializer

对于每个显示的调查,我必须显示与其相关的开关数据,并且在开关对象内部我需要在其中显示吸烟者对象,因此每个调查对象必须看起来像这样

{
        "id": 11,
        "switch": {
            "id": 12,
            "smoker": {
               "firstname":"sami",
               "lastname:"hamad",
               "mobile":"7983832",
               "gender":"0",
               "age":"2",
               "occupation":"2"
          },
            "time": null,
            "count_outers": 5,
            "count_packs": 7,
            "new_brand": 2,
            "new_sku": 2
        },
        "date": "2018-12-08",
        "bool_switch": true,
        "user": 7,
        "reason": 3,
        "shift": 2,
        "current_brand": 6,
        "current_sku": 4,
        "pos": 2
    },

但是当我发出 POST 请求时,它给了我这个错误

/api/v2/surveysync/ 处的 ValueError 无法分配 "OrderedDict([('first_name', 'aline'), ('last_name', 'youssef'), ('mobile', 7488483), ('gender', False), ('age', ), ('职业', )])": "Switch.smoker" 必须是 一个“吸烟者”实例。

所以请帮忙,非常感谢!

【问题讨论】:

  • 您的 switchSerializer 创建方法没有返回语句?
  • @c6754 我添加了它,同样的错误
  • 在你的代码中是序列化器还是 Meta 类上的 create 方法?
  • 我没有为它定义创建方法
  • ?在 SwitchSerializer 中,您在 Meta 类上定义了一个 create 方法,而不是序列化类本身。

标签: django serialization django-rest-framework


【解决方案1】:

您走在正确的道路上,但您手动保存了开关对象,而不是让SwitchSerializer 为您做这件事。与开关序列化程序中的 create 方法相同。应该是这样的:

class SmokerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Smoker
        fields = '__all__'

class SwitchSerializer(serializers.ModelSerializer):
    smoker = SmokerSerializer()
    class Meta:
        model = Switch
        fields = '__all__'
    def create(self, validated_data):
       smoker_data = validated_data.pop('smoker', None)
       if smoker_data:
         serializer = SmokerSerializer(data=smoker_data, context=self.context)
         if serializer.is_valid():    
            validated_data['smoker'] = serializer.save()
       return super().create(validated_data)

class SurveySerializer(serializers.ModelSerializer):
    switch = SwitchSerializer()

    class Meta:
        model = Survey
        fields = '__all__'
    def create(self, validated_data):

        switch_data = validated_data.pop('switch', None)
        if switch_data:
            serializer = SwitchSerializer(data=switch_data, context=self.context)
            if serializer.is_valid():
                validated_data['switch'] = serializer.save()
        return super().create(validated_data)

【讨论】:

  • 它给了我你必须先打电话给.is_valid(),然后再打电话给.save()
  • @AndrehAbboud 我已经更新了我的答案以解决这个问题
  • @AndrehAbboud 我忘了删除其中一种保存方法。做到了。自己调试很困难,因为我只是在写它而不是在运行它
  • 看人插入工作但它正在添加开关 null { "id": 13, "switch": null, "date": "2018-12-10", "bool_switch": true, "user": 4, "reason": 3, "shift": 2, "current_brand": 5, "current_sku": 5, "pos": 2 } 并且开关包含吸烟者对象
  • 这就是我在回答中试图解释的。您正在尝试使用吸烟者的 json 而不是吸烟者对象来创建开关。您是否意识到在您的代码中,switchserializer 的 create 方法永远不会被调用?这就是我在回答中更正的内容。
【解决方案2】:

SwitchSerializer 中,您将create 函数定义为内部Meta 类的方法,而不是SwitchSerializer 类的成员。试试这个

class SwitchSerializer(serializers.ModelSerializer):
    smoker = SmokerSerializer()
    class Meta:
        model = Switch
        fields = '__all__'
    def create(self, validated_data):
       smoker_data = validated_data.pop('smoker', None)
       if smoker_data:
           smoker = Smoker.objects.create(**smoker_data)
           validated_data['smoker'] = smoker
       return Switch.objects.create(**validated_data)

【讨论】:

    猜你喜欢
    • 2019-03-16
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多