Django如何根据主机名动态修改urlpatterns?
Django按主机名动态生成URL路由方案
核心思路
不用创建多个urls.py文件,而是通过动态生成URL配置结合请求中间件,根据当前请求的主机名匹配对应的URL路径,将同一视图映射到不同路径上。
实现步骤
1. 定义主机名-路径映射表
在项目的settings.py中添加映射规则和默认值:
# settings.py HOST_PATH_MAPPINGS = { 'www.example.com': {'article_path': 'articles/'}, 'www.example.it': {'article_path': 'articolo/'}, 'www.example.de': {'article_path': 'artikel/'}, } DEFAULT_HOST_PATHS = {'article_path': 'articles/'}
2. 编写动态生成路由的函数
在项目根目录的urls.py中,创建根据主机名生成对应路由的函数,并加入缓存避免重复生成:
# urls.py from django.urls import path from . import views # 缓存已生成的路由,提升性能 _url_pattern_cache = {} def get_host_urlpatterns(hostname): if hostname in _url_pattern_cache: return _url_pattern_cache[hostname] from django.conf import settings # 获取当前主机的路径配置,无匹配则用默认值 path_config = settings.HOST_PATH_MAPPINGS.get(hostname, settings.DEFAULT_HOST_PATHS) # 生成对应路由 patterns = [ path(path_config['article_path'], views.articles, name='articles'), # 可添加更多路由规则,复用同一逻辑 ] _url_pattern_cache[hostname] = patterns return patterns # 默认路由(启动时加载,实际请求会被中间件覆盖) urlpatterns = get_host_urlpatterns('default')
3. 编写主机名路由中间件
创建中间件文件middlewares.py,在每个请求进来时动态设置URL配置:
# middlewares.py from . import urls class HostBasedURLMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 提取主机名(去除端口号) hostname = request.get_host().split(':')[0].lower() # 动态生成当前主机的URL配置类 dynamic_urlconf = type( 'DynamicURLConf', (), {'urlpatterns': urls.get_host_urlpatterns(hostname)} ) # 为当前请求设置自定义URL配置 request.urlconf = dynamic_urlconf response = self.get_response(request) return response
4. 注册中间件
在settings.py的MIDDLEWARE列表中添加自定义中间件:
# settings.py MIDDLEWARE = [ # 保持原有中间件顺序,将自定义中间件放在靠近顶部的位置 'yourapp.middlewares.HostBasedURLMiddleware', # ... 其他中间件 ]
原理说明
Django允许通过request.urlconf为每个请求单独指定URL配置。中间件在请求到达时,根据主机名调用路由生成函数,创建临时的URL配置类,让当前请求使用该配置完成路由解析,从而实现同一视图对应不同主机名的不同URL路径。
内容的提问来源于stack exchange,提问作者Philipp S.
相关产品推荐
相关产品推荐

