运行环境
本地:win10 企业版 版本号1809(64位)
虚拟机:VMware Workstation Pro 15.0.2 build-10952284
虚拟机系统:Ubuntu 18.04.2 LTS
python版本:3.7.2(本地+虚拟机)
Django版本: 2.1.7
uWSGI版本:2.0.18(64位)
问题:django项目在本地以python manage.py runserver的形式运行时功能正常,但在以uWSGI+nginx形式部署到Ubuntu,浏览器访问url,视图渲染过滤器的html时报错,详细报错情况如下:
TemplateSyntaxError at /‘news_filters’ is not a registered tag library. Must be one of:
admin_list admin_modify admin_static admin_urlscachehighlighti 18nl 10n log more_like_this payinfo_filters rest_framework static staticfiles tz
即在渲染template模板时,我的app下面的templatetags文件夹(已包含__init__文件)中的news_filters过滤器没有正常加载,提示过滤器没有注册,上文列出的是django环境自带的filter或者tag,在网上搜索之后,有人说要在settings.py文件中的TEMPLATES列表中添加libraries,即下文libraries的部分:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'front', 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'builtins':[
'django.templatetags.static',
],
'libraries': {
'news_filters': 'app.news.templatetags.news_filters',
},
},
},
]
我按照news_filters.py文件的路径进行添加之后依然报错,信息如下:
InvalidTemplateLibrary at /
Invalid template library specified. ImportError raised when trying to load ‘app.news.templatetags.news_filters’: No module named ‘app.news.templatetags’
提示没有templatetags这个app,templatetags确实不是一个app,app.news才是一个app,因此我只加载了app.news(见下文),于是我将 ‘news_filters’: ‘app.news.templatetags.news_filters’改为’news_filters’: ‘app.news’,重新运行依然报错:
Module app.news does not have a variable named ‘register’
提示app没有’register’变量,我考虑’register’应该在news_filters.py中,于是我将app.news.templatetags.news_filters作为一个app添加进settings.py的INSTALLED_APPS列表中:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app.cms',
'app.xfzauth',
'app.news',
'app.news.templatetags.news_filters',
'app.course',
'app.ueditor',
'app.payinfo',
'rest_framework',
'debug_toolbar',
'haystack',
]
并将libraries中的’news_filters’: ‘app.news.‘重新改为’news_filters’: ‘app.news.templatetags.news_filters’,再次运行没有报错,虽然问题得到了临时性的解决,但随之又有新的问题出现,对在另一个template模板中的payinfo_filters过滤器我采取了相同的操作,但依然报错,而且是服务器的内部错误:
Traceback (most recent call last):
File “./xfz/wsgi.py”, line 16, in
application = get_wsgi_application()
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/core/wsgi.py”, line 12, in get_wsgi_application
django.setup(set_prefix=False)
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/init.py”, line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/apps/registry.py”, line 89, in populate
app_config = AppConfig.create(entry)
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/apps/config.py”, line 90, in create
module = import_module(entry)
File “/root/HOME/.virtualenvs/django/lib/python3.6/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “./app/payinfo/templatetags/payinfo_filters.py”, line 10, in
from app.payinfo.models import PayinfoOrder
File “./app/payinfo/models.py”, line 13, in
class Payinfo(models.Model):
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/db/models/base.py”, line 87, in new
app_config = apps.get_containing_app_config(module)
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/apps/registry.py”, line 249, in get_containing_app_config
self.check_apps_ready()
File “/root/HOME/.virtualenvs/django/lib/python3.6/site-packages/django/apps/registry.py”, line 132, in check_apps_ready
raise AppRegistryNotReady(“Apps aren’t loaded yet.”)
django.core.exceptions.AppRegistryNotReady: Apps aren’t loaded yet.
unable to load app 0 (mountpoint=’’) (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
提示没有app被加载,这样的话肯定是无法正常运行的,从报错信息的加粗部分可以看到,问题出在我在payinfo_filters.py中导入了自定义app数据库模型,即:
from app.payinfo.models import PayinfoOrder
我思考只要在过滤器(.py文件)中导入了自定义app中的任意模块或函数,按照前文提到的方法的话应该都会报错,所以通过添加过滤器的python文件到INSTALL_APPS列表的方法并不能很好的解决问题。但是显然因为我在本地运行是良好的,问题应该出在uWSGI或者ubuntu系统上,重新装虚拟机比较麻烦,而uWSGI出问题的可能性更大,重新查看最初的详细的报错信息:
Request Method: GET
Request URL: http://192.168.75.200:8000/
Django Version: 2.1.7
Exception Type: TemplateSyntaxError
Exception Value:
TemplateSyntaxError at /‘news_filters’ is not a registered tag library. Must be one of:
admin_list admin_modify admin_static admin_urlscachehighlighti 18nl 10n log more_like_this payinfo_filters rest_framework static staticfiles tz
Exception Location: /root/HOME/.virtualenvs/django/lib/python3.7/site-packages/django/template/defaulttags.py in find_library, line 1024
Python Executable: /usr/local/bin/uwsgi
Python Version: 3.7.2
从加粗的地方可以看到,defaulttags.py in find_library函数报错,defaulttags.py文件路径在python虚拟环境下,find_library函数代码如下:
def find_library(parser, name):
try:
return parser.libraries[name]
except KeyError:
raise TemplateSyntaxError(
"'%s' is not a registered tag library. Must be one of:\n%s" % (
name, "\n".join(sorted(parser.libraries)),
),
)
报错语句为return parser.libraries[name],即没有在parse类实例的libraries[ ]列表中找到自定义的news_filters模块(或者叫库,也就是.py文件),我么再来看一下parse类实例的初始化代码(Parse类位于与defaulttags.py路径相同的base.py文件中):
class Parser:
def __init__(self, tokens, libraries=None, builtins=None, origin=None):
self.tokens = tokens
self.tags = {
}
self.filters = {
}
self.command_stack = []
if libraries is None:
libraries = {
}
if builtins is None:
builtins = []
self.libraries = libraries
for builtin in builtins:
self.add_library(builtin)
self.origin = origin
很明显这里并没有对libraries列表进行赋值,我们查找一下对Parse类的引用,只有在同文件的Template类下的compile_nodelist函数进行了实例化,代码如下:
def compile_nodelist(self):
"""
Parse and compile the template source into a nodelist. If debug
is True and an exception occurs during parsing, the exception is
is annotated with contextual line information where it occurred