我使用线程本地来实现基于用户的主题。首先,我写了一个中间件,没有任何问题。现在我将它转换为装饰者,并有一个令人尴尬的问题。这是简化的代码:
# views.py
_thread_locals = threading.local()
def foo_decorator(f):
def _wrapper(*args, **kwargs):
global _thread_locals
_thread_locals.bar = kwargs['bar']
return f(*args, **kwargs)
return wraps(f)(_wrapper)
@foo_decorator
def some_view(request, bar):
# Stuff here
# Here _thread_locals.bar exists
# This is called by the template loader:
def get_theme():
return _thread_locals.bar # Error
调用get_theme时我得到的是条形属性不存在的投诉。哪里消失了?最有可能的是我错过了与闭包中的范围有关的内容,但无法弄清楚是什么。
答案 0 :(得分:0)
您的代码适用于我,但仅限于some_view
之前调用get_theme
。
每次修改项目目录中的文件时,devserver都会终止您的进程并重新启动一个新进程。完成后,您的线程数据当然会丢失。如果您看到"Validating models..."
消息,则您的线程数据已丢失。
答案 1 :(得分:0)
更改django模板加载器以支持主题是我所做的。
`def load_template_for_user(user, template_name):
"""
Loads a template for a particular user from a theme.
This is used in the generic baseviews and also in the theme template tags
1. First try and load the template with the users theme.
2. Second if that doesn't exist, try and load the template from the default theme
3. Send the template name to the loader to see if we can catch it.
4. With the order of the template loaders, the template loader above will try and
load from the Database.
This will happen if the user tries to use {% extends %} or {% include %} tags
"""
_theme = get_theme_for_user(user)
_theme_template_name = "" + _theme.name + "/templates/" + template_name
# Get the default theme
_default_theme = get_default_theme()
_default_theme_template_name = "" + _default_theme.name + "/templates/" + template_name
_templates=[_theme_template_name, _default_theme_template_name, template_name]
try:
return loader.select_template(_templates)
except TemplateDoesNotExist, e:
log.error("Couldn't load template %s" % template_name)
raise
except Exception, e:
log.error("Couldn't load template, generic Exception %s" % e)
raise
`
显然有一些代码在那里你看不到,但它基本上看模型看看default_theme是什么,而get_theme_for_user查看UserProfile对象以查看他们设置主题的内容。