【问题标题】:Django Rest Framework nested writable fields mixins drf_writable_nestedDjango Rest Framework 嵌套可写字段 mixins drf_writable_nested
【发布时间】:2019-03-18 16:07:58
【问题描述】:

我目前正在尝试使用drf_writable_nested 来更新和创建我当前的数据库架构,但我一直面临这个错误:

.create() 方法默认不支持可写嵌套字段。 为序列化器trvl.serializers.StatisticsSerializer 写一个显式的.create() 方法,或者在嵌套的序列化器字段上设置read_only=True

主要型号:

class Statistics(models.Model):
    """Instance: {airport_code, carrier_code, month, year, flight, delay_count, delay_time}"""
    airport = models.ForeignKey(Airport, on_delete=models.CASCADE)
    carrier = models.ForeignKey(Carrier, on_delete=models.CASCADE)
    month = models.IntegerField(
        validators=[MinValueValidator(1), MaxValueValidator(12)])
    year = models.IntegerField(validators=[MinValueValidator(
        1900, message='Invalid year: year < 1900.')])
    # statistics linkage
    flight = models.ForeignKey(
        FlightStatistics, on_delete=models.DO_NOTHING)
    delay_count = models.ForeignKey(
        DelayCountStatistics, on_delete=models.DO_NOTHING)
    delay_time = models.ForeignKey(
        DelayTimeStatistics, on_delete=models.DO_NOTHING)

    # Guaranteeing the "primary key" of the tuple
    class Meta:
        unique_together = ('airport', 'carrier', 'month', 'year')

    def __str__(self):
        return '%s_%s_%s_%s' % (self.airport, self.carrier, self.month, self.year)

序列化器:

class StatisticsSerializer(WritableNestedModelSerializer):
    # Using nest serializer for handling get and post
    # Using serializers instead of the model fields
    flight = FlightStatisticsSerializer()
    delaycount = DelayCountStatisticsSerializer()
    delaytime = DelayTimeStatisticsSerializer()

    class Meta:
        model = models.Statistics
        fields = ('airport', 'carrier', 'month', 'year',
                  'flight', 'delaytime', 'delaycount')

查看:

class StatisticsView(viewsets.ModelViewSet, NestedCreateMixin, NestedUpdateMixin):
queryset = models.Statistics.objects.all()
serializer_class = serializers.StatisticsSerializer

def post(self,request,*args, **kwargs):
    return self.create(request, *args, **kwargs)

def put(self, request, *args, **kwargs):
    return self.update(request, *args, **kwargs)

有效负载示例:

{
    "airport": "ATL",
    "carrier": "AA",
    "month": 7,
    "year": 2008,
    "flight": {
        "cancelled": 2,
        "on_time": 30,
        "total": 100l,
        "delayed": 303,
        "diverted": 121
    },
    "delaytime": {
        "late_aircraft": 21,
        "weather": 2121,
        "security": 2121,
        "national_aviation_system": 21212,
        "carrier": 22
    },
    "delaycount": {
        "late_aircraft": 1212,
        "weather": 1212,
        "security": 1221,
        "national_aviation_system": 1221,
        "carrier": 1212
    }
}

此视图的 Django HTML 表单:

【问题讨论】:

    标签: python django django-rest-framework django-views mixins


    【解决方案1】:

    更新

    我决定实现自己的嵌套序列化器:

    class StatisticsSerializer(serializers.ModelSerializer):
        # Using nest serializer for handling get and post
        # Using serializers instead of the model fields
        url = serializers.HyperlinkedIdentityField(view_name='statistics-detail')
        flight = FlightStatisticsSerializer(allow_null=True)
        delay_count = DelayCountStatisticsSerializer(allow_null=True)
        delay_time = DelayTimeStatisticsSerializer(allow_null=True)
    
        class Meta:
            model = models.Statistics
            fields = ('url','airport', 'carrier', 'month', 'year',
                      'flight', 'delay_time', 'delay_count')
    
        def create(self, validated_data):
            flight_statistics = models.FlightStatistics.objects.create(
                **(validated_data.pop('flight')))
            delay_time_statistics = models.DelayTimeStatistics.objects.create(
                **(validated_data.pop('delay_time')))
            delay_count_statistics = models.DelayCountStatistics.objects.create(
                **(validated_data.pop('delay_count')))
            print(flight_statistics)
    
            statistics = models.Statistics.objects.create(**validated_data, flight=flight_statistics,
                                                          delay_time=delay_time_statistics, delay_count=delay_count_statistics)
    
            return statistics
    
        def update(self, instance, validated_data):
            flight, _ = models.FlightStatistics.objects.update_or_create(id=instance.flight.id, defaults=validated_data.pop('flight'))
            delay_time, _ = models.DelayTimeStatistics.objects.update_or_create(id=instance.delay_time.id, defaults=validated_data.pop('delay_time'))
            delay_count, _ = models.DelayCountStatistics.objects.update_or_create(id=instance.delay_count.id, defaults=validated_data.pop('delay_count'))
            new_instance, _ = models.Statistics.objects.update_or_create(id=instance.id, defaults=validated_data)
    
            return new_instance
    

    【讨论】:

      【解决方案2】:

      您是否尝试过执行错误消息中的建议?

      class StatisticsSerializer(WritableNestedModelSerializer):
          # Using nest serializer for handling get and post
          # Using serializers instead of the model fields
          flight = FlightStatisticsSerializer(read_only=True)         # <--
          delaycount = DelayCountStatisticsSerializer(read_only=True) # <--
          delaytime = DelayTimeStatisticsSerializer(read_only=True)   # <--
      
          class Meta:
              model = models.Statistics
              fields = ('airport', 'carrier', 'month', 'year',
                        'flight', 'delaytime', 'delaycount')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-20
        • 1970-01-01
        • 2023-01-10
        • 2020-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多