簡體   English   中英

KeyError:帶有 ModelSerializer 的 DRF 中的“請求”

[英]KeyError: 'request' in DRF with ModelSerializer

序列化程序.py

from rest_framework import serializers
from .models import Flight, Segment, Airport


class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        fields = self.context['request'].query_params.get('fields')
        if fields:
            fields = fields.split(',')
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)


class SegmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Segment
        fields = (  # TODO - Could be __all__ if no fine tuning
            'id', 'flight_id', 'dep_code', ...
        )


class FlightSerializer(DynamicFieldsModelSerializer, serializers.ModelSerializer):
    segments = SegmentSerializer(many=True, source='segment_set')

    class Meta:
        model = Flight
        fields = (  # TODO - Could be __all__ if no fine tuning
            'id', 'dep_air', 'dest_air', ...
        )


class AirportSerializer(DynamicFieldsModelSerializer, serializers.ModelSerializer):
    dep_air = FlightSerializer(many=False, source='dep_air_airport')

    class Meta:
        model = Airport
        fields = ('iata_code', 'name', 'continent', 'iso_country',)

啟動服務器時出現以下錯誤:

  File "/Users/me/PycharmProjects/fly_baby/flight_data/serializers.py", line 55, in AirportSerializer
    dep_air = FlightSerializer(many=False, source='dep_air_airport')
  File "/Users/me/PycharmProjects/fly_baby/flight_data/serializers.py", line 15, in __init__
    fields = self.context['request'].query_params.get('fields')
KeyError: 'request'

目標是將航班嵌套在機場下,反之亦然,但當我使用 DynamicFieldsModelSerializer 混合時似乎不可能。 init請求 self.context['request'] 對於下一行不存在

dep_air = FlightSerializer(many=False, source='dep_air_airport')

我相信我是以某種方式傳遞上下文的,但我不知道考慮到我的泛型重設置怎么可能。

額外代碼::

視圖.py

class AirportFlightViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = FlightSerializer

    def get_queryset(self):
        return Flight.objects.filter(flight=self.kwargs['airport_pk'])

網址.py

router = DefaultRouter()
router.register(r'flights', views.FlightViewSet)
router.register(r'segments', views.SegmentViewSet)
router.register(r'airports', views.AirportViewSet)

flights_router = routers.NestedSimpleRouter(router, r'flights', lookup='flight')
flights_router.register(r'segments', views.FlightSegmentViewSet, basename='flight-segments')

airports_router = routers.NestedSimpleRouter(router, r'airports', lookup='airport')
airports_router.register(r'flights', views.AirportFlightViewSet, basename='airport-flights')

urlpatterns = [
    path('', views.index),
    path('api/', include(router.urls)),
    path('api/', include(flights_router.urls)),
    path('api/', include(airports_router.urls)),
]

您可以編輯DynamicFieldsModelSerializer以不依賴於存在的上下文,因此可以使用.get()在沒有它的情況下構建它:

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        request = self.context.get('request')

        if request:
            fields = request.query_params.get('fields')
            if fields:
                ...  # code as before

但是請注意,當像這樣使用子序列化程序(在本例中為FlightSerializer )時,將始終應用所有字段。 但是,這是有道理的,因為在請求機場時,您希望fields參數影響機場的字段,而不是航班的字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM