簡體   English   中英

Django Rest Framework在POST中接收主鍵值並將模型對象作為嵌套序列化器返回

[英]Django Rest Framework receive primary key value in POST and return model object as nested serializer

我不完全確定我的問題的標題是我想要的那樣具體,但事實是這樣的:

我有一個HyperlinkedModelSerializer ,如下所示:

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    carpool = SchoolBuildingCarpoolSerializer()

    class Meta:
        model = ParentArrival

正如您所看到的, carpool被定義為嵌套的序列化程序對象,我想要的是能夠以這種方式發出POST請求以創建ParentArrival (數據為application / json):

{
    ...
    "carpool": "http://localhost:8000/api/school-building-carpools/10/"
    ...
}

並以這種方式接收數據:

{
    "carpool": {
        "url": "http://localhost:8000/api/school-building-carpools/10/"
        "name": "Name of the carpool",
        ...
    }
}

基本上,我正在尋找一種處理嵌套序列化程序的方法,而不必在POST請求中將數據作為對象(但在這種情況下為id或url)發送,但接收對象嵌套在序列化響應中。

我對以前的解決方案感到滿意,但我決定重新審視,我認為我有另一種解決方案可以完全滿足您的需求。

基本上,您需要創建自己的自定義字段,並且只需覆蓋to_representation方法:

class CarpoolField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        pk = super(CarpoolField, self).to_representation(value)
        try:
           item = ParentArrival.objects.get(pk=pk)
           serializer = CarpoolSerializer(item)
           return serializer.data
        except ParentArrival.DoesNotExist:
           return None

    def get_choices(self, cutoff=None):
        queryset = self.get_queryset()
        if queryset is None:
            return {}

        return OrderedDict([(item.id, str(item)) for item in queryset])

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    carpool = CarpoolField(queryset=Carpool.objects.all())

    class Meta:
        model = ParentArrival

這將允許您發布

{
     "carpool": 10
}

得到:

{
    "carpool": {
        "url": "http://localhost:8000/api/school-building-carpools/10/"
        "name": "Name of the carpool",
        ...
    }
}

這很簡單。 如您所知, Django appends "_id" to the field name ModelClass中Django appends "_id" to the field name ,您可以在SerializerClass中實現它,並且還可以實現原始Django appends "_id" to the field name 你所要做的就是這樣

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    # ...
    carpool_id = serializers.IntegerField(write_only=True)
    carpool = SchoolBuildingCarpoolSerializer(read_only=True)
    # ...
    class Meta:
        fields = ('carpool_id', 'carpool', ...)

並在POST請求中使用carpool_id

一種方法是將“拼車”保持為DRF的默認值,然后為嵌套對象添加只讀字段。

像這樣的東西(我沒有時間測試代碼,所以請考慮這個偽代碼。如果你不能讓它工作,請告訴我,並將花更多的時間):

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    carpool_info = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = ParentArrival
        fields = ('id', 'carpool', 'carpool_info',)

    def get_carpool_info(self, obj):
         carpool = obj.carpool
         serializer = SchoolBuildingCarpoolSerializer(carpool)
         return serializer.data

如果您的唯一嵌套對象是拼車,我還建議切換到常規ModelSerializer,因此拼車只顯示ID(10),然后嵌套對象可以顯示URL。

 class ParentArrivalSerializer(serializers.ModelSerializer):
     ....

然后,如果一切正常,你將能夠發一個帖子

{
     "carpool": 10
}

而你得到:

{
    "carpool": 10
    "carpool_info": {
        "url": "http://localhost:8000/api/school-building-carpools/10/"
        "name": "Name of the carpool",
        ...
    }
}

我從來沒有找到另一個解決方案,所以這是我多次使用的技巧。

覆蓋to_representation方法怎么樣?

class YourSerializer(serializers.ModelSerializer):

    class Meta:
        model = ModelClass
        fields = ["id", "foreignkey"]

    def to_representation(self, instance):
        data = super(YourSerializer, self).to_representation(instance)
        data['foreignkey'] = YourNestedSerializer(instance.foreignkey).data
        return data

暫無
暫無

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

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