2016-06-21 76 views
4

我有兩個模型(Like和News)。我使用django-rest-framework來製作一個web api。django rest框架 - 請求上下文關鍵錯誤

class Like(models.Model): 
    user = models.ForeignKey(User) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey('content_type', 'object_id') 

class News(models.Model): 
    user = models.ForeignKey(User) 
    title = models.CharField(max_length=150) 
    ... 
    likes = GenericRelation(Like) 

一個狀物體有它自己的用戶字段來存儲誰喜歡的新聞對象。現在要檢查某個特定的用戶是否存在於某個News對象中,我從SerializerMethodField獲取request.user。

class NewsSerializer(serializers.HyperlinkedModelSerializer): 
    user = UserSerializer() 
    likes_count = serializers.IntegerField(source='likes.count', read_only=True) 
    user_in_likes = serializers.SerializerMethodField() 

    class Meta: 
     model = News 
     fields = ('user', 'title', 'body', 'article_image', 'pub_date', 'likes_count', 'user_in_likes') 

    def get_user_in_likes(self, obj): 
     user = self.context['request'].user 
     what = obj.likes.filter(user=user).exists() 
     return what 

當我去/新聞/ URL,我得到的JSON對象包括user_in_likes到真/假每個新聞對象。

不過,我還有一個serialzer對於其中進口NewsSerializer class和其他類似的串行化不同的模式:

class ActivityObjectRelatedField(serializers.RelatedField): 
    def to_representation(self, value): 
     if isinstance(value, User): 
      serializer = UserSerializer(value) 
     elif isinstance(value, Job): 
      serializer = JobSerializer(value) 
     elif isinstance(value, News): 
      serializer = NewsSerializer(value) 
     elif isinstance(value, Tender): 
      serializer = TenderSerializer(value) 
     else: 
      raise Exception('Unexpected type of tagged object') 
     return serializer.data  

class ActivitySerializer(serializers.HyperlinkedModelSerializer): 
    actor = ActivityObjectRelatedField(read_only=True) 
    target = ActivityObjectRelatedField(read_only=True) 

    class Meta: 
     model = Activity 
     fields = ('url', 'actor', 'verb', 'target', 'pub_date') 

現在,如果我訪問/activities/,以獲得活動對象,我得到一個錯誤:

KeyError at /activities/

'request'

它指向使用self.context['request'].user的NewsSerialize類的SerializerMethod行。

Exception Location: /vagrant/myproject/news/serializers.py in get_user_in_likes, line 25

再次,如果我訪問/news/網址,一切都很好,我得到的消息對象。我在這裏錯過了什麼?爲什麼request不被ActivitiesSerializer class識別?請幫我解決這個問題。謝謝。

回答

5

您收到此錯誤,因爲to_representation()方法實例化NewsSerializer類或其它類似的串行當你沒有在上下文傳遞request

您正在to_representation()方法中手動實例化特定的串行器類。因此,在實例化之後,該特定串行器無法訪問ActivitySerializercontext,從而導致該錯誤。

您可以passActivitySerializercontextto_representation()方法有關串行的實例期間。

class ActivityObjectRelatedField(serializers.RelatedField): 
    def to_representation(self, value): 
     if isinstance(value, User): 
      serializer = UserSerializer(value, context=self.context) # pass context 
     elif isinstance(value, Job): 
      serializer = JobSerializer(value, context=self.context) # pass context 
     elif isinstance(value, News): 
      serializer = NewsSerializer(value, context=self.context) # pass context 
     elif isinstance(value, Tender): 
      serializer = TenderSerializer(value, context=self.context) # pass context 
     else: 
      raise Exception('Unexpected type of tagged object') 
     return serializer.data  
+0

非常感謝您的先生! – Aamu

+0

非常有幫助 – po5i

2

看起來好像你沒有在/activities/的視圖中填入你的請求的context字典NewsSerializer

您可能使用了由Django REST Framework提供的基於類的視圖,該視圖爲您填充此字典(請參閱get_serializer_context() method)並將其傳遞給Serializer實例。這就是爲什麼它可以在您的序列化程序中自動在您的/news/視圖中使用。

但是,在您的/activities/視圖中,上下文會傳遞到ActivitySerializer,並且不會(自動)從那裏繼續傳播。這就是爲什麼NewsSerializer的上下文字典中沒有request鍵。您需要將您的請求對象傳遞給NewsSerializer實例。要將額外的上下文傳遞給串行器,可以在實例化時添加包含字典的context參數(請參閱DRF documentation)。