'django.template.context_processors.request' django-tables2 和 django-admin-tools 的问题
'django.template.context_processors.request' issue with django-tables2 and django-admin-tools
我在使用 django-admin-tools(0.8.0) 和 django-tables2(1.5) 时尝试在 Django(1.10.4) 中通过 xhtml2pdf 呈现 PDF 时遇到问题) 一起。我已经做了足够多的阅读以了解正在发生的事情的基础,但不知道如何解决它。我认为这与 django-admin-tools 自定义加载器有关。
Link 到 exception 我从 django-tables 得到。
这 让我问了一个问题。
我想要做的事情的要点是通过 django-admin 界面中 AdminModel 的下拉框创建自定义 Admin 'action',将给定的查询集转换为 PDF 文档。
根据 django-tables2 docs render() 函数有 3 个参数(请求,'template_name.html',{'people':Person.objects.all()})。所以我向我的 context_dict 添加了一个查询集,并尝试在下面模板的 for 循环中使用它,但没有骰子。该模板在没有 django-tables2 的情况下将 html 呈现为 pdf 就好了,但是如果我尝试将表格转换为 PDF,我会得到以下信息...
回溯
Environment:
Request Method: POST
Request URL: http://127.0.0.1:9999/admin/research/labsample/
Django Version: 1.10.4
Python Version: 3.5.2
Installed Applications:
('admin_tools',
'admin_tools.theming',
'admin_tools.menu',
'admin_tools.dashboard',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_tables2',
'import_export',
'chemicals',
'suppliers',
'customers',
'recipes',
'research')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Template error:
In template /home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templates/django_tables2/table.html, error at line 13
Tag {% querystring %} requires django.template.context_processors.request to be in the template configuration in settings.TEMPLATES[]OPTIONS.context_processors) in order for the included template tags to function correctly. 3 :
4 : <div class="table-container">
5 : {% block table %}
6 : <table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
7 : {% block table.thead %}
8 : {% if table.show_header %}
9 : <thead>
10 : <tr>
11 : {% for column in table.columns %}
12 : {% if column.orderable %}
13 : <th {{ column.attrs.th.as_html }}><a href=" {% querystring table.prefixed_order_by_field=column.order_by_alias.next %} ">{{ column.header }}</a></th>
14 : {% else %}
15 : <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
16 : {% endif %}
17 : {% endfor %}
18 : </tr>
19 : </thead>
20 : {% endif %}
21 : {% endblock table.thead %}
22 : {% block table.tbody %}
23 : <tbody>
Traceback:
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
39. response = get_response(request)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in wrapper
544. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/sites.py" in inner
211. return view(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapper
67. return bound_func(*args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in bound_func
63. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in changelist_view
1569. response = self.response_action(request, queryset=cl.get_queryset(request))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in response_action
1305. response = func(self, request, queryset)
File "/home/dan/Projects/research/mysite/research/admin.py" in GeneratePdf
27. pdf = render_to_pdf('pdf/quote_recipe.html', content)
File "/home/dan/Projects/research/mysite/research/utils.py" in render_to_pdf
40. html = template.render(context_dict)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
208. return self._render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
209. nodelist.append(node.render_annotated(context))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templatetags/django_tables2.py" in render
154. return template.render(context.flatten())
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
208. return self._render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/loader_tags.py" in render
61. result = self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/loader_tags.py" in render
61. result = self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
315. return nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
209. nodelist.append(node.render_annotated(context))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
315. return nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templatetags/django_tables2.py" in render
59. raise ImproperlyConfigured(context_processor_error_msg % 'querystring')
Exception Type: ImproperlyConfigured at /admin/research/labsample/
Exception Value: Tag {% querystring %} requires django.template.context_processors.request to be in the template configuration in settings.TEMPLATES[]OPTIONS.context_processors) in order for the included template tags to function correctly.
自定义管理功能
def GeneratePdf(self, request, queryset):
data = queryset.values()
content = {}
rec = RecipeIngredients.objects.filter(recipe_id=data.values()[0]['lab_recipe_id'])
content.update({'recipe':{rec.values()}})
content.update(data[0])
pdf = render_to_pdf('pdf/quote_recipe.html', content)
return HttpResponse(pdf, content_type='application/pdf')
我的utils.py
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result, link_callback=link_callback)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
我的settings.py模板配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS':[BASE_DIR+'/templates/',],
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.template.context_processors.debug',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'loaders':[
'admin_tools.template_loaders.Loader',
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]
},
},
]
PDF 模板
{% load render_table from django_tables2 %}
{% load static %}
<!doctype html>
<html>
<body>
{% for r in recipe %}
{% render_table r %}
{% endfor %}
</body>
</html>
要使用模板上下文处理器,您必须在呈现模板时传递 request
对象:
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict, request=request)
...
您可以使用 render_to_string
.
稍微简化代码
from django.template.loader import render_to_string
def render_to_pdf(template_src, context_dict=None):
if context_dict is None:
context_dict = {}
html = render_to_string(template_src, context_dict, request=request)
...
顺便说一句,您在定义函数时不应该 use mutable values as defaults。在上面的第二个示例中,我展示了如何通过使用 None
作为默认值来避免问题。
我在使用 django-admin-tools(0.8.0) 和 django-tables2(1.5) 时尝试在 Django(1.10.4) 中通过 xhtml2pdf 呈现 PDF 时遇到问题) 一起。我已经做了足够多的阅读以了解正在发生的事情的基础,但不知道如何解决它。我认为这与 django-admin-tools 自定义加载器有关。
Link 到 exception 我从 django-tables 得到。
这
我想要做的事情的要点是通过 django-admin 界面中 AdminModel 的下拉框创建自定义 Admin 'action',将给定的查询集转换为 PDF 文档。
根据 django-tables2 docs render() 函数有 3 个参数(请求,'template_name.html',{'people':Person.objects.all()})。所以我向我的 context_dict 添加了一个查询集,并尝试在下面模板的 for 循环中使用它,但没有骰子。该模板在没有 django-tables2 的情况下将 html 呈现为 pdf 就好了,但是如果我尝试将表格转换为 PDF,我会得到以下信息...
回溯
Environment:
Request Method: POST
Request URL: http://127.0.0.1:9999/admin/research/labsample/
Django Version: 1.10.4
Python Version: 3.5.2
Installed Applications:
('admin_tools',
'admin_tools.theming',
'admin_tools.menu',
'admin_tools.dashboard',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_tables2',
'import_export',
'chemicals',
'suppliers',
'customers',
'recipes',
'research')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Template error:
In template /home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templates/django_tables2/table.html, error at line 13
Tag {% querystring %} requires django.template.context_processors.request to be in the template configuration in settings.TEMPLATES[]OPTIONS.context_processors) in order for the included template tags to function correctly. 3 :
4 : <div class="table-container">
5 : {% block table %}
6 : <table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
7 : {% block table.thead %}
8 : {% if table.show_header %}
9 : <thead>
10 : <tr>
11 : {% for column in table.columns %}
12 : {% if column.orderable %}
13 : <th {{ column.attrs.th.as_html }}><a href=" {% querystring table.prefixed_order_by_field=column.order_by_alias.next %} ">{{ column.header }}</a></th>
14 : {% else %}
15 : <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
16 : {% endif %}
17 : {% endfor %}
18 : </tr>
19 : </thead>
20 : {% endif %}
21 : {% endblock table.thead %}
22 : {% block table.tbody %}
23 : <tbody>
Traceback:
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
39. response = get_response(request)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in wrapper
544. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/sites.py" in inner
211. return view(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapper
67. return bound_func(*args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/utils/decorators.py" in bound_func
63. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in changelist_view
1569. response = self.response_action(request, queryset=cl.get_queryset(request))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/contrib/admin/options.py" in response_action
1305. response = func(self, request, queryset)
File "/home/dan/Projects/research/mysite/research/admin.py" in GeneratePdf
27. pdf = render_to_pdf('pdf/quote_recipe.html', content)
File "/home/dan/Projects/research/mysite/research/utils.py" in render_to_pdf
40. html = template.render(context_dict)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
208. return self._render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
209. nodelist.append(node.render_annotated(context))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templatetags/django_tables2.py" in render
154. return template.render(context.flatten())
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
208. return self._render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/loader_tags.py" in render
61. result = self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/loader_tags.py" in render
61. result = self.nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
315. return nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
209. nodelist.append(node.render_annotated(context))
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/defaulttags.py" in render
315. return nodelist.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render
994. bit = node.render_annotated(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django/template/base.py" in render_annotated
961. return self.render(context)
File "/home/dan/Projects/research/lib/python3.5/site-packages/django_tables2/templatetags/django_tables2.py" in render
59. raise ImproperlyConfigured(context_processor_error_msg % 'querystring')
Exception Type: ImproperlyConfigured at /admin/research/labsample/
Exception Value: Tag {% querystring %} requires django.template.context_processors.request to be in the template configuration in settings.TEMPLATES[]OPTIONS.context_processors) in order for the included template tags to function correctly.
自定义管理功能
def GeneratePdf(self, request, queryset):
data = queryset.values()
content = {}
rec = RecipeIngredients.objects.filter(recipe_id=data.values()[0]['lab_recipe_id'])
content.update({'recipe':{rec.values()}})
content.update(data[0])
pdf = render_to_pdf('pdf/quote_recipe.html', content)
return HttpResponse(pdf, content_type='application/pdf')
我的utils.py
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result, link_callback=link_callback)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
我的settings.py模板配置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS':[BASE_DIR+'/templates/',],
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.template.context_processors.debug',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'loaders':[
'admin_tools.template_loaders.Loader',
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]
},
},
]
PDF 模板
{% load render_table from django_tables2 %}
{% load static %}
<!doctype html>
<html>
<body>
{% for r in recipe %}
{% render_table r %}
{% endfor %}
</body>
</html>
要使用模板上下文处理器,您必须在呈现模板时传递 request
对象:
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict, request=request)
...
您可以使用 render_to_string
.
from django.template.loader import render_to_string
def render_to_pdf(template_src, context_dict=None):
if context_dict is None:
context_dict = {}
html = render_to_string(template_src, context_dict, request=request)
...
顺便说一句,您在定义函数时不应该 use mutable values as defaults。在上面的第二个示例中,我展示了如何通过使用 None
作为默认值来避免问题。