簡體   English   中英

Django Rest Framework:單個嵌套請求中的POST和PUT

[英]Django Rest Framework: POST and PUT in a single nested request

我正在使用Django Rest Framework創建對象。 JSON也包含嵌套的對象。 創建並鏈接到“主要對象”的對象數組,以及應該部分更新的對象。

JSON看起來像這樣:

{
  "opcitem_set" : [
    {
      "comment" : "Test comment",
      "grade" : "1",
      "name" : "1a"
    },
    {
      "comment" : "Test comment",
      "grade" : "2",
      "name" : "1b"
    },
    {
      "description" : "Additional test item",
      "comment" : "Additional comment",
      "grade" : "1",
      "name" : "extra_1"
    }
  ],
  "is_right_seat_training" : false,
  "checked_as" : "FC",
  "date" : "2015-10-23",
  "check_reason" : "Check ride",
  "opc_program" : "2",
  "is_pc" : true,
  "questionnaire_test_passed" : "Passed",
  "pnf_time" : 2,
  "other_comments_complete_crew" : "Other comments",
  "other_comments_flying_pilot" : "Other comments",
  "is_cat_2_training" : false,
  "opc_passed" : "Passed",
  "pilot" : {
    "pc_valid_to" : "2015-10-23",
    "id" : 721,
    "email" : "jens.nilsson@nextjet.se",
    "total_time" : 3120,
    "medical_valid_to" : "2015-10-23"
  },
  "pf_time" : 2,
  "aircraft_type" : "S340",
  "typeratingexaminer" : 734
}

“ opcitem_set”包含應創建的OpcItem類型的對象,並且該對象具有主對象的ForeignKey。 到目前為止,我可以通過重寫ModelSerializer上的create()方法(如http://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations中所述)來實現。

然后我們有“飛行員”對象的情況。 這將始終包含一個ID和一些其他字段以修補具有該ID的對象。

“ typeratingexaminer”字段只是另一個“ Pilot”對象,但不應對其進行修補,而應將其設置為外鍵。

我的問題是:是否可以在create()方法中修補(部分更新)“試驗”,還是會破壞某種設計模式? 由於它實際上是PATCH而不是POST,因此在原始請求完成后,我是否應該在單獨的請求中執行此操作? 在那種情況下,我是否可以有一個跨兩個請求的事務,以便如果第二個請求失敗,則第一個請求將被回滾?

希望能夠僅從客戶端發送一個請求,而不是將其拆分為兩個請求。 也許您可以將ViewSet中已經存在的JSON分離出來,然后將其發送到其他序列化器?

很高興聽到您對此的想法,我有點迷茫。

如果您不是在創建主要對象而是僅創建嵌套對象,則應在序列化程序中重寫.update()方法,並執行以下操作:

def update(self, instance, validated_data):

    if 'opcitem_set' in validated_data:
        opcitem_set_data = validated_data.pop('opcitem_set')

    if 'pilot' in validated_data:
        pilot_data = validated_data.pop('pilot')

    ...

    for opcitem_set in opcitem_set_data:
        Opcitem.objects.create(main_object=instance,
                               **opcitem_set)

    current_pilot = self.instance.pilot
    current_pilot.pc_valid_to = pilot_data.get('name', current_pilot.pc_valid_to)
    ...
    current_pilot.save()

    """
    Update instance as well if you need
    """

    return instance

如果還需要創建主對象,則需要重寫.create()方法。 但是,那么PATCHing pilot並不是真正做到這一點的好方法。

我建議不要使用序列化器的create方法,並在視圖中構建廣泛的邏輯,在這種情況下,您可以在需要的地方充分利用更簡單,笨拙的序列化器。 您可以在序列化器的create方法中進行更新,但突然之間不再是序列化器,它更多地是一個控制器,因此最好通過覆蓋create或post方法將其放置在視圖代碼中; 這種設計使您只能從客戶端收到一個請求,可以在視圖代碼中處理請求數據,並使用簡單的序列化程序來實例化/更新對象,並根據需要進行嵌入式數據驗證。

如果您可以共享模型和序列化器,那么我們也許可以發表更多評論。

暫無
暫無

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

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