2014-03-03 95 views
4

當字段必須在Django REST框架編程填充,則pre_save方法可以在APIView重寫的字段,和所需的字段可以在那裏進行填充,如:Django的其餘框架填充嵌套對象編程

def pre_save(self, obj): 
    obj.owner = self.request.user 

這適用於平面對象,但在嵌套情況下,嵌套對象無法在pre_save方法中訪問。我目前發現的唯一解決方案是覆蓋save_object方法,並檢查對象是否是嵌套類的實例,如果是,則在那裏填充該字段。雖然這有效,但我不喜歡該解決方案,並想知道是否有人找到更好的方法?

演示情況:

class Notebook(models.Model): 
    owner = models.ForeignKey(User) 

class Note(models.Model): 
    owner = models.ForeignKey(User) 
    notebook = models.ForeignKey(Notebook) 
    note = models.TextField() 

class NoteSerializer(serializers.ModelSerializer): 
    owner = serializers.Field(source='owner.username') 
    class Meta: 
     model = Note 
     fields = ('note', 'owner') 

class NotebookSerializer(serializers.ModelSerializer): 
    notes = NoteSerializer(many=True) 
    owner = serializers.Field(source='owner.username') 
    class Meta: 
     model = Notebook 
     fields = ('notes', 'owner') 

    def save_object(self, obj, **kwargs): 
     if isinstance(obj, Note): 
      obj.owner = obj.notebook.owner 

     return super(NotebookSerializer, self).save_object(obj, **kwargs) 

class NotebookCreateAPIView(CreateAPIView): 
    model = Notebook 
    permission_classes = (IsAuthenticated,) 
    serializer_class = NotebookSerializer 

    def pre_save(self, obj): 
     obj.owner = self.request.user 

問我爲什麼不使用不同的端點分別建立筆記本電腦和筆記,讓我說,我這樣做之前,但我也需要一個功能,以提供初始筆記關於筆記本的創建,所以我也需要這種端點。另外,在我想出這個黑客解決方案之前,我實際上預計我將不得不重寫NoteSerializer類本身的save_object方法,但事實證明,在嵌套對象的情況下,它甚至不會被調用,只有根對象的所有嵌套對象的方法save_objects,但我想這是一個設計決定。

所以再一次,這是可以用更習慣的方式解決嗎?

回答

3

您可以在您的序列化上下文中訪問請求。

所以我的方法,這將是:

class NoteSerializer(serializers.ModelSerializer): 
    owner = serializers.Field(source='owner.username') 

    def restore_object(self, attrs, instance=None): 
     instance = super(NoteSerializer, self).restore_object(attrs, instance) 
     instance.owner = self.context['request'].user 
     return instance 

    class Meta: 
     model = Note 
     fields = ('note', 'owner') 

而且在NotebookSerializer相同。

串行器上下文將被提供給ViewSet中所有使用的串行器。

+0

dammit,這真的看起來不錯,我會試試這個並回復給你,謝謝,直到 – andrean

+0

工作確實,謝謝:) – andrean