我在Django上写了一些内容管理系统。用户可以使用各种网址创建页面。对于页面路由,我使用的是默认的django url路由器机制:
pages = CMSHelpers().get_available_pages()
urlpatterns = patterns(
'',
url(r'^$', include('app.home.site.urls', namespace='homepage')),
url(r'^search/', include('app.search.site.urls', namespace='search')),
url(r'^ajax/', include('app.ajax.site.urls', namespace='ajax')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
for page in pages:
if page.module.slug:
try:
urlpatterns += patterns(
'',
url(
'^%s/' % page.url.strip('/'),
include(
'app.%s.site.urls' % page.module.slug,
namespace=page.module.slug + '-' + page.module_params
),
kwargs={'page_data': page}
)
)
logging.debug("Imported url %s for module %s" % (page.url.strip('/'), page.module.slug))
except ImportError:
logging.debug("Cannot import urls.py for module %s" % page.module.slug)
continue
else:
continue
urlpatterns += patterns('',
url(r'^captcha/', include('captcha.urls')),
)
问题:
当django app启动时,python会缓存所有urlpatterns。当用户通过CMS更改某个页面的url时,我正在重新加载urlpatterns 但仅针对当前的uwsgi进程/线程:
urlconf = settings.SUBDOMAIN_URLCONFS["www"]
clear_url_caches()
reload(sys.modules[urlconf])
reloaded = import_module(urlconf)
if hasattr(reloaded, 'urlpatterns'):
reloaded_urls = getattr(reloaded, 'urlpatterns')
set_urlconf(tuple(reloaded_urls))
因此,当用户尝试在网站上访问此页面时,会收到随机404错误。
那么,我如何为所有uwsgi进程/线程重新加载模块 ?
答案 0 :(得分:0)
将用户创建的模式保存到数据库中。
编写一些填充url模式的中间件来搜索每个页面请求。
然后你可以拥有任意数量的线程。我怀疑开销可以忽略不计。
答案 1 :(得分:0)
鉴于像这样的网络应用通常使用“无共享”架构,在每个请求上检查某种外部数据存储实际上是合理的。所述外部数据存储可以具有更新时间戳,每个工作线程/进程与它们自己的最后更新时间戳进行比较,并且如果它是较新的则决定重新加载该模块。
但是,更好的方法是为r'^(?P<url>.*)/$'
这样的页面添加一个catchall url模式,并将其路由到一个处理程序,该处理程序查找特定页面的处理程序应该是什么并调用它。
答案 2 :(得分:0)
我遇到了同样的问题。我不想在每个错过的URL上点击数据库。我只想在发生变化时重新加载URL。
由于我们使用uwsgi来运行所有django进程,因此我通过向Uwsgi进程发送HUP信号来强制从shell重新加载。
在django进程中,我只想向父进程发送HUP信号,这是uwsgi进程。所以我添加了这两行:
import os, signal
os.kill( os.getppid(), signal.SIGHUP )
我希望这有帮助!