DRF пост запрос нескольких внутренних сериализаторов - PullRequest
0 голосов
/ 08 декабря 2018

У меня есть три модели с именами Smoker, Switch, Survey. У меня есть курильщик в качестве внешнего ключа в модели 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-запрос, он выдаёт мне эту ошибку

ValueError в / api / v2 /surveyysync / Невозможно назначить "OrderedDict ([('first_name', 'aline'), ('last_name', 'youssef'), (" mobile ", 7488483), (" sex ", False), (" age ",), ('профессия',)]) ":" Switch.smoker "должен быть экземпляром" Smoker ".

, поэтому, пожалуйста, помогите и большое вам спасибо!

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

В 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)
0 голосов
/ 08 декабря 2018

Вы идете по правильному пути, но сохраняете объекты переключателя вручную, вместо того, чтобы SwitchSerializer делал это за вас.То же самое с методом создания в переключателе сериализатора.Должно быть так:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...