【问题标题】:Wagtail API v2 django.template.exceptions.TemplateDoesNotExistWagtail API v2 django.template.exceptions.TemplateDoesNotExist
【发布时间】:2020-05-22 17:59:07
【问题描述】:

我已经按照docs 的规定配置了Wagtail API,并且在使用curl 时效果很好:

$ curl -LsD- http://127.0.0.1:8080/rest/p/
HTTP/1.1 200 OK
Date: Fri, 22 May 2020 17:33:58 GMT
Server: WSGIServer/0.2 CPython/3.8.2
Content-Type: application/json
Vary: Accept, Cookie
Allow: GET, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Length: 433
X-Content-Type-Options: nosniff

{
    "meta": {
        "total_count": 1
    },
    "items": [
        {
            "id": 2,
            "meta": {
                "type": "wagtailcore.Page",
                "detail_url": "http://localhost/rest/p/2/",
                "html_url": "http://localhost/",
                "slug": "home",
                "first_published_at": null
            },
            "title": "Welcome to your new Wagtail site!"
        }
    ]
}

Wagtail 文档声明如下:

(可选),您可能还想将 rest_framework 添加到 INSTALLED_APPS。这将使 API 在从 Web 浏览器查看时可浏览,但对于基本的 JSON 格式输出不是必需的。

这是真的,因为 API 通过curl 可以正常工作,但是如果我不将rest_framework 添加到INSTALLED_APPS 然后尝试通过浏览器访问相同的网址,我会得到http 500,即因为应用程序抛出异常:

Internal Server Error: /rest/p/
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "/usr/local/lib/python3.8/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "/usr/local/lib/python3.8/site-packages/rest_framework/response.py", line 70, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "/usr/local/lib/python3.8/site-packages/rest_framework/renderers.py", line 723, in render
    template = loader.get_template(self.template)
  File "/usr/local/lib/python3.8/site-packages/django/template/loader.py", line 19, in get_template
    raise TemplateDoesNotExist(template_name, chain=chain)
django.template.exceptions.TemplateDoesNotExist: rest_framework/api.html

所以在我看来,如果我不想用django 例外来堵塞我的电子邮件,那么rest_framework 是我的产品站点设置中的强制性应用程序吗?我错过了一些配置细节吗?解决此问题的最佳方法是什么?

我不希望我的实时网站一直抛出 500,而且我也不需要这个漂亮而闪亮的 api 界面。


编辑:

添加了相关的rest_framework配置:

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticatedOrReadOnly",
    ],
    "DEFAULT_RENDERER_CLASSES": [
        "rest_framework.renderers.JSONRenderer",
    ],
}

编辑:

通过查看调试回溯,Wagtail 似乎以某种方式强制执行 rest_framework.renderers.BrowsableAPIRenderer 渲染器,即使 REST_FRAMEWORK 未配置为使用它?

编辑:

显然Wagtail 确实忽略了REST_FRAMEWORK 设置,而是使用硬编码的renderer_classes,即[JSONRenderer, BrowsableAPIRenderer]

【问题讨论】:

    标签: python django django-rest-framework wagtail wagtail-apiv2


    【解决方案1】:

    这是因为rest_frameworkTemplateHTMLRenderer 作为默认渲染器之一。

    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
           'rest_framework.renderers.JSONRenderer',
           'rest_framework.renderers.TemplateHTMLRenderer',
        ],
       ...
    }
    

    为了渲染模板,它必须使用 Django 模板工具来定位它们。为了让该工具在rest_framework 包中搜索模板,必须将其添加到INSTALED_APPS

    因此,要解决此问题,请覆盖 REST_FRAMEWORK 设置并删除 TemplateHTMLRenderer,因为您只需要 JSONRenderer。 你可以阅读更多关于DRF settings的信息。

    【讨论】:

    • 请查看已编辑的问题,我已经添加了我的 rest_framework 配置。
    【解决方案2】:

    可能是Wagtail 中的bug,因为它忽略了设置中的REST_FRAMEWORK 配置,而是使用硬编码的renderer_classes,目前是[JSONRenderer, BrowsableAPIRenderer]

    为了克服这个问题,可以像下面这样设置Wagtail API

    from django.conf import settings
    from wagtail.api.v2.views import PagesAPIViewSet
    from wagtail.api.v2.router import WagtailAPIRouter
    
    if not settings.DEBUG:
        from rest_framework.renderers import JSONRenderer
    
        class ProdPagesAPIViewSet(PagesAPIViewSet):
            renderer_classes = [JSONRenderer]
    
        PagesAPIViewSet = ProdPagesAPIViewSet
    
    api_router = WagtailAPIRouter("wagtailapi")  
    api_router.register_endpoint("p", PagesAPIViewSet)
    

    【讨论】:

      猜你喜欢
      • 2020-10-01
      • 2020-06-29
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 2014-10-14
      • 2019-01-28
      • 1970-01-01
      相关资源
      最近更新 更多