django rest framework - 请求上下文密钥错误

时间:2016-06-21 16:41:53

标签: json django django-rest-framework

我有两个模特(喜欢和新闻)。我正在使用django-rest-framework来制作一个web api。

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)

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

当我去/ news / url时,我会为每个新闻对象获取包含user_in_likes的json对象为true / false。

但是,我有另一个用于导入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/,要获取活动对象,我会收到错误:

  

/ activities /

中的KeyError      

'请求'

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

  

异常位置:/vagrant/myproject/news/serializers.py in get_user_in_likes,第25行

再次,如果我访问/news/网址,一切都很好,我得到新闻对象。我在这里错过了什么?为什么request无法识别ActivitiesSerializer class?请帮我解决这个问题。谢谢。

2 个答案:

答案 0 :(得分:5)

您收到此错误是因为request方法中实例化NewsSerializer类或其他类似序列化程序时未在上下文中传递to_representation()

您正在to_representation()方法中手动实例化特定的序列化程序类。因此,在实例化之后,该特定序列化程序无法访问ActivitySerializer context,从而导致错误。

ActivitySerializer方法中,您可以 pass context to_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 Array.prototype.findFirstSubstring = function(s) { for(var i = 0; i < this.length;i++) { if(this[i].indexOf(s) !== -1) return i; } return -1; }; 实例化相关序列化程序。

i.findFirstSubstring('height');

答案 1 :(得分:2)

您似乎没有在context视图中填写NewsSerializer字典/activities/字段。

您可能使用Django REST Framework提供的基于类的视图,它为您填充此字典(请参阅get_serializer_context() method)并将其传递给Serializer实例。这就是/news/视图中序列化程序自动可用的原因。

但是,在/activities/视图中,上下文会传递给ActivitySerializer,并且不会(自动)从那里进一步传播。这就是request的上下文字典中没有NewsSerializer键的原因。您需要将请求对象传递给NewsSerializer实例。要将额外的上下文传递给Serializer,您可以在实例化时添加包含字典的context参数(请参阅DRF documentation)。