我有两个模特(喜欢和新闻)。我正在使用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
?请帮我解决这个问题。谢谢。
答案 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)。