在Django REST Framework中渲染服务器端JSON

时间:2016-01-09 20:49:19

标签: json django request django-rest-framework

我正在尝试通过将整个数据库序列化为JSON来进行批量数据下载。 onTouchEvent() implementation有一个部分说明你可以这样做:

context={'request': request}

不幸的是,这对HyperLinked关系不起作用。当你尝试用它们做的时候,你会得到类似的东西:

  

AssertionError:r = Request(request=HttpRequest()) context = dict(request=r) serializer = CommentSerializer(comment, context=context) json = JSONRenderer().render(serializer.data) 需要序列化程序上下文中的请求。在实例化序列化程序时添加lookup_field

所以,我发现我可以添加上下文属性,例如:

r = Request(request=RequestFactory().get(reverse('comment-list', kwargs={'version': 'v3'})))
context = dict(request=r)
serializer = CommentSerializer(comment, context=context)
json = JSONRenderer().render(serializer.data)

然后返回错误:

  

django.core.exceptions.ImproperlyConfigured:无法使用视图名称“opinioncluster-detail”解析超链接关系的URL。您可能未能在API中包含相关模型,或者在此字段上错误地配置了lookup_field属性。

我知道这个API在从浏览器调用时可以正常工作,但是当我如上所述调用它时,我无法理解它。当您手动渲染时,浏览器不会自动执行某些操作。

有什么想法吗?

首先编辑

这是另一种看似有希望的策略,因为它会为我的请求对象添加路径:

class OpinionClusterViewSet(LoggingMixin, viewsets.ModelViewSet):
    queryset = OpinionCluster.objects.all()
    serializer_class = OpinionClusterSerializer
    filter_class = OpinionClusterFilter
    ordering_fields = (
        'date_created', 'date_modified', 'date_filed', 'citation_count',
        'date_blocked',
    )

返回相同的问题,好像我没有定义请求的路径:

  

django.core.exceptions.ImproperlyConfigured:无法使用视图名称“opinioncluster-detail”解析超链接关系的URL。您可能未能在API中包含相关模型,或者在此字段上错误地配置了class OpinionClusterSerializer(DynamicFieldsModelSerializer, serializers.HyperlinkedModelSerializer): absolute_url = serializers.CharField(source='get_absolute_url', read_only=True) panel = serializers.HyperlinkedRelatedField( many=True, view_name='judge-detail', read_only=True, ) non_participating_judges = serializers.HyperlinkedRelatedField( many=True, view_name='judge-detail', read_only=True, ) docket = serializers.HyperlinkedRelatedField( many=False, view_name='docket-detail', read_only=True, ) sub_opinions = serializers.HyperlinkedRelatedField( many=True, view_name='opinion-detail', read_only=True, ) class Meta: model = OpinionCluster 属性。

第二次编辑

正如我在评论中所说,我非常肯定我的序列化程序和视图不应该受到责备,因为它们通过浏览器完美地运行。不过,他们在这里。如果你真的很慷慨,那就是完整的序列化器,过滤器和代码库getSpans()

查看

class EmailGroup(models.Model):
   name = models.CharField(max_length=100)
   users = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='email_groups')

串行

contrib.auth

2 个答案:

答案 0 :(得分:0)

此管理命令创建一个MockRequest以在非浏览器环境中使用,并允许您创建JSON:

from django.core.management.base import BaseCommand
from django.http import HttpRequest

from rest_framework.renderers import JSONRenderer
from rest_framework.request import Request

from comments.models import Comment
from comments.serializers import CommentSerializer


class MockRequest(HttpRequest):

    def __init__(self):
        super(MockRequest, self).__init__()
        self.setup_host()

    def setup_host(self):
        # Required to give absolute urls in output
        self.META['HTTP_HOST'] = 'localhost:8000'  


class Command(BaseCommand):
    help = 'Export JSON'

    def handle(self, *args, **options):
        request = MockRequest()

        serializer_context = {
            'request': Request(request),
        }

        comment = Comment.objects.first()

        serializer = CommentSerializer(comment, context=serializer_context)
        json = JSONRenderer().render(serializer.data)

        print(json)

要删除硬编码域,您可以使用Sites框架为主机名提供支持:

def setup_host(self):
    from django.contrib.sites.models import Site
    site = Site.objects.get_current()
    self.META['HTTP_HOST'] = site.domain

答案 1 :(得分:0)

在深入挖掘代码之后,我终于想出了这个:

r = RequestFactory().request()
r.version = 'v3'
r.versioning_scheme = URLPathVersioning()
context = dict(request=r)
renderer = JSONRenderer()
json_str = renderer.render(
    serializer(item, context=context).data,
    accepted_media_type='application/json; indent=2',
)

这似乎有效,但序列化的JSON中的HyperLinkRelated值将服务器设置为testserver。我可以通过设置来解决这个问题:

r.META['SERVER_NAME']

但我还需要将r.scheme设置为https,这似乎不可能(我收到错误r.scheme无法设置)。

我很接近,所以现在必须作为答案。