如何在Django中程序化添加URL模式?

12 投票
4 回答
4549 浏览
提问于 2025-04-16 11:02

有没有办法在不重启服务器的情况下,程序matically地给Django添加网址模式?

或者有没有办法强制Django重新处理或缓存网址模式(URLconf)?

4 个回答

3

这是你的答案:

import sys
from django.conf import settings
from importlib import reload
from django.urls import clear_url_caches

urlconf = settings.ROOT_URLCONF
  if urlconf in sys.modules:
      clear_url_caches()
      reload(sys.modules[urlconf])
3

我尝试过一些方法,修改了 django.core.urlresolvers 里的东西——这对我有效,但要注意这只是个小技巧。我现在没有代码了,但大概做了以下几步:

  1. Django 通常使用 urlresolvers.get_resolver() 来获取一个 RegexURLResolver,这个东西负责处理网址。把 None 传给这个函数可以得到你的“根” URL 配置。
  2. get_resolver() 会使用一个缓存,叫 _resolver_cache,来存储加载过的 URL 配置。
  3. 重置 _resolver_cache 应该能强制 Django 重新创建一个干净的 URL 解析器。

另外,你也可以试着取消根 RegexURLResolver_urlconf_module 属性,这样应该能强制 Django 重新加载它(不过我不太确定,因为这个模块可能会被 Python 缓存)。

from urlresolvers import get_resolver

delattr(get_resolver(None), '_urlconf_module')

再次强调,这个方法不一定有效(我只是凭记忆说的,之前的代码我显然是出于某种原因删掉了)。但 django/core/urlresolvers.py 绝对是你需要查看的文件。

编辑:我决定试试这个,但结果没有成功……

编辑2:

果然,你的 URL 模块会被 Python 缓存。简单地在它们变化时重新加载可能有效(使用 reload)。如果你的问题是根据一些可能变化的数据动态构建 urlpatterns

我尝试了重新加载我的根 URL(project.urls)和一个子 URL 模块(app.urls)。这就是我需要做的,新的 URL 就能通过 get_resolver(None).url_patterns 显示出来。

所以这个小技巧可能就是这么简单:手动重新加载你的 URL 模块。

4

如果你使用gunicorn而没有预加载代码,只需给gunicorn的主进程发送一个HUP信号,它就会启动新的工作进程来加载新代码,同时优雅地关闭旧的工作进程,这样就不会丢失任何请求!

撰写回答