2015-07-28 25 views
3

我有一個HyperlinkedModelSerializer。爲了正確實施它的validate方法,我需要訪問主鍵正在驗證的對象的URL - 如果它有一個,即它是編輯,則不會創建。這樣做的正確方法是什麼?Django REST框架:在驗證過程中獲取ID/URL?

我試過很多東西,但只是工作的方法是,取對象的ID時,串行實例化爲它的id領域的黑客:

class BoxSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = Box 
     fields = ('id', 'name', 'url') 

    def __init__(self, *args, **kwargs): 
     super(BoxSerializer, self).__init__(*args, **kwargs) 
     self.id = None \ 
      if len(args) != 1 or not isinstance(args[0], Box) \ 
      else args[0].id 

    def validate(self, data): 
     print(data) 
     return data 

什麼是訪問ID的正確方法/序列化程序的validate方法中正在驗證的對象的URL? data['id']data['url']都不存在。


urls.py

urlpatterns = [ 
    url(r'(?P<pk>[0-9]+)/$', views.BoxDetail.as_view(), name='box-detail'), 
] 

views.py

class BoxDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = Box.objects.all() 
    serializer_class = BoxSerializer 

回答

3

您可以訪問該對象的id通過self.instance正在編輯。上Accessing the initial data and instance:

從DRF串行文檔當通過初始對象或查詢集到串行器實例, 對象將提供作爲.instance。如果沒有初始對象 傳遞則.instance屬性將None

由於您使用HyperLinkedModelSerializer,你將有機會獲得該對象在PUT請求爲instance屬性上串行設置的情況下進行編輯。您可以使用此instance屬性來訪問對象的idself.instance.id正在編輯。

您可以在validate()函數中編寫驗證邏輯,然後在變量object_id中獲取對象ID。這不會影響創建請求,因爲instance將不會在串行器上設置。

class BoxSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = Box 
     fields = ('id', 'name', 'url') 

    def validate(self, data): 
     if self.instance: # 'instance' will be set in case of `PUT` request i.e update 
      object_id = self.instance.id # get the 'id' for the instance 
      # write your validation logic based on the object id here 

     return data 

的另一種方式訪問該對象ID是由在串行context字典從view對象訪問kwargs

my_view = self.context['view'] # get the 'view' object from serializer context 
object_id = my_view.kwargs.get('pk') # access the 'view' kwargs and lookup for 'pk' 
+0

出於好奇:你從哪裏知道?文檔是否說這個*任何地方*?我可以發誓我讀了整個文檔*兩次*尋找這個。 – theV0ID

+0

我遇到了類似的問題,然後必須查看DRF的源代碼,以瞭解對象是否被設置爲串行器的變量。此外,DRF序列化程序文檔中還略微提及了這一點。我已經使用該頁面鏈接更新了ans。我認爲檢查DRF的源代碼以及文檔有助於改進。 :) –

+0

謝謝!看起來我要學習閱讀。 – theV0ID

0

調用具有context屬性的序列化。

serializer = BoxSerializer(queryset, context={'request': self.request}, ...) 

現在你可以從validate功能訪問request對象與

self.context['request']['id'] 
+0

我使用'generics.RetrieveUpdateDestroyAPIView'用'serializer_class = MySerializer'指令,但'self.context [ '請求'] [ 'ID']'從內的串行的'validate'方法給出我是'TypeError':*''Request'對象不可以代數「* – theV0ID

+0

在你的情況下,你必須覆蓋'get_serializer_class()'方法。 –

+0

在附註上,如果一個對象實現'__getitem __()'函數(egs是列表,元組,字典和字符串),它就是可下標的。 'request'對象不是字典,我們不能使用'['id']'來訪問變量。我們需要使用'.'運算符。 'id'也不會作爲'request'對象的屬性出現。 –

相關問題