DRF发布请求多个内部串行器

时间:2018-12-08 11:56:41

标签: django serialization django-rest-framework

我有三个模型,分别命名为Smoker,Switch,Survey。我将Smoker作为Switch模型的外键,而将switch作为Survey模型的外键

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',),   ('occupation',)])“”:“ Switch.smoker”必须为   一个“吸烟者”实例。

所以请帮助并非常感谢您!

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:0)

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)