使用Django REST API的ValidationError和用于通用外键可写访问的generic_relations

时间:2014-07-26 11:40:32

标签: python django django-rest-framework generic-foreign-key generic-relations

我正在使用Django REST API和generic_relations模块为Django Comments创建一种变体,它不是由模板驱动,而是通过REST API函数驱动。

名为Annotation的Model类,如:

class Annotation(BaseCommentAbstractModel):

    paragraph_id = models.PositiveIntegerField(null=False)

    body = models.TextField()
    '''
    Annotations can be written only by logged in users. It is to prevent hit and run comments by people under anonymity.
    '''
    user = models.ForeignKey(DjangoUser, null=False, verbose_name=_('user'), related_name = "annotations")

现在,还有另一个内容模型,它可以是几乎任何东西,所以我们可以说,这是一个简单的发布应用程序:

class BlogContent(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='')
    body = models.TextField()
    ...
    annotation = GenericRelation(Annotation, content_type_field='content_type', object_id_field='object_pk')

序列化器的外观如下:

from generic_relations.relations import GenericRelatedField 

class BlogContentSerializer(serializers.ModelSerializer):
    author_id = serializers.Field(source='author_id.username')
    annotation = serializers.RelatedField(many=True)

    class Meta:
        model = BlogContent
        fields = ('title','created','author_id',
              'data','published_flag', 'url_path','slug','annotation')

class AnnotationSerializer(serializers.ModelSerializer):
    user = serializers.Field(source='user.username')
    content_object = GenericRelatedField({
        BlogContent: serializers.HyperlinkedRelatedField(view_name='annotation:blogcontent-detail'),
        }, read_only=False)

    class Meta:
        model = Annotation
        fields = ('paragraph_id', 'body', 'user', 'content_object')


class UserSerializer(serializers.ModelSerializer):
    blogcontent= serializers.PrimaryKeyRelatedField(many=True) 
    annotations = serializers.PrimaryKeyRelatedField(many=True)

    class Meta:
        model = User
        fields = ('username', 'id', 'blogcontent', 'annotations')

现在,问题在于:     content_object = GenericRelatedField({             BlogContent:serializers.HyperlinkedRelatedField(view_name ='annotation:blogcontent-detail'),             },read_only = False)

如果要将通用关系设置为只读,通过设置read_only=True,则REST API可浏览性很好,但是当我将其切换到False时,服务器会抛出一个ValidationError

ValidationError at /en/annotation/
[u'Invalid model - model not available.']

仔细阅读日志和代码,似乎rest_framework.renderers.py get_raw_data_form(self, view, method, request) obj = getattr(view, 'object', None)未在通话field_to_native中找到对象。

反过来,在serializer = self.determine_deserializer_for_data(value)中将generic_relations函数评估为value时,导致不会将任何内容传递为/home/craft/pirateenv/lib/python2.7/site-packages/django/core/handlers/base.py in get_response response = response.render() ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/django/template/response.py in render self.content = self.rendered_content ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/response.py in rendered_content ret = renderer.render(self.data, media_type, context) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/renderers.py in render context = self.get_context(data, accepted_media_type, renderer_context) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/renderers.py in get_context raw_data_post_form = self.get_raw_data_form(view, 'POST', request) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/renderers.py in get_raw_data_form content = renderer.render(serializer.data, accepted, context) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/serializers.py in data self._data = self.to_native(obj) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/rest_framework/serializers.py in to_native value = field.field_to_native(obj, field_name) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/generic_relations/relations.py in field_to_native serializer = self.determine_deserializer_for_data(value) ... ▶ Local vars /home/craft/pirateenv/lib/python2.7/site-packages/generic_relations/relations.py in determine_deserializer_for_data raise ValidationError(self.error_messages['no_model_match']) ... ▶ Local vars ,因此代码会中断。

是否还有其他人遇到此类错误和/或可以帮我修复它?请帮忙!

回溯如下:

{{1}}

1 个答案:

答案 0 :(得分:0)

This issue on the repository也提到同样的错误,但在不同的上下文中,所提供的解决方案对我也有效,直到作者发布修复时为止。

解决方案是在调用if value:方法后添加super子句。