您现在的位置是: 网站首页 >Django Django

Django多子域名路由配置方案django-hosts

admin2019年5月21日 15:46 Django | Html | JQuery 1411人已围观

# Django多子域名路由配置方案django-hosts 效果 - `http://www.mydomain.cn/api/` --> `http://api.mydomain.cn/` - `http://www.mydomain.cn/blog/` --> `http://blog.mydomain.cn/` - `http://www.mydomain.cn/` --> `http://www.mydomain.cn/` 保持不变 同一个app实现 ## 原方案 ![BLOG_20190521_154957_13](/media/blog/images/2019/05/BLOG_20190521_154957_13.png "博客图集BLOG_20190521_154957_13.png") ```python # DjangoHostsTest/settings.py ALLOWED_HOSTS = [ '.mydomain.cn', # 匹配.mydomain.cn的所有域名 ] ``` 修改主机的hosts,以支持域名访问本地服务,且服务运行在80端口`run server 0.0.0.0:80`测试。 ```ini 127.0.0.1 www.mydomain.cn 127.0.0.1 blog.mydomain.cn 127.0.0.1 api.mydomain.cn ``` ### 项目主urls ```python # 项目urls from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('blog/', include('blog.urls', namespace='blog')), path('api/', include('api.urls', namespace='api')), path('', include('www.urls', namespace='www')), ] ``` ### 项目 www - url ```python # www ruls apps/www/urls.py from django.urls import path from .views import index app_name = 'www' urlpatterns = [ path('', index, name='index'), ] ``` ```html <!-- apps/www/templates/www/index.html --> <h2>项目主页</h2> <h4><a href="{% url 'blog:index' %}">博客</a></h4> <h4><a href="{% url 'api:index' %}">接口</a></h4> ``` 访问 http://www.mydomain.cn/ ![BLOG_20190521_154940_88](/media/blog/images/2019/05/BLOG_20190521_154940_88.png "博客图集BLOG_20190521_154940_88.png") ### 博客 blog - url ```python # blog urls apps/blog/urls.py from django.urls import path from .views import index, blog_list, blog_detail app_name = 'blog' urlpatterns = [ path('', index, name='index'), path('list/', blog_list, name='list'), path('detail/<str:blog_id>/', blog_detail, name='detail'), ] ``` ```html <!-- apps/blog/templates/blog/index.html --> <h2>BLOG主页</h2> <a href="{% url 'blog:list' %}">进入BLOG列表</a> ``` ![BLOG_20190521_154929_12](/media/blog/images/2019/05/BLOG_20190521_154929_12.png "博客图集BLOG_20190521_154929_12.png") ```html <!-- apps/blog/templates/blog/list.html --> <h4><a href="{% url 'blog:index' %}">返回BLOG主页</a></h4> <ul> <li><a href="{% url 'blog:detail' 1 %}">进入BLOG详情1</a></li> <li><a href="{% url 'blog:detail' 2 %}">进入BLOG详情2</a></li> </ul> ``` ![BLOG_20190521_154918_40](/media/blog/images/2019/05/BLOG_20190521_154918_40.png "博客图集BLOG_20190521_154918_40.png") ```html <!-- apps/blog/templates/blog/detail.html --> <h2>BLOG详情</h2> <h4><a href="{% url 'blog:list' %}">返回BLOG列表</a></h4> <b>BLOG正文:</b> 当前访问的ID:{{ blog_id }} ``` ![BLOG_20190521_154907_35](/media/blog/images/2019/05/BLOG_20190521_154907_35.png "博客图集BLOG_20190521_154907_35.png") ## django-hosts配置 实现 `http://www.mydomain.cn/blog/` --> `http://blog.mydomain.cn/` 现在如果直接访问 http://blog.mydomain.cn/ 是显示的项目主页,因为没有具体路径的url都由`path('', include('www.urls', namespace='www')),`去匹配 ![BLOG_20190521_154855_18](/media/blog/images/2019/05/BLOG_20190521_154855_18.png "博客图集BLOG_20190521_154855_18.png") ### 安装 ```Shell pip install django-hosts ``` ### 配置settings.py 添加 `django_hosts` 到 `INSTALLED_APPS` ```python # DjangoHostsTest/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog.apps.BlogConfig', 'api.apps.ApiConfig', 'www.apps.WwwConfig', 'django_hosts', # pip install django-hosts 安装,添加app(第1步) ] ``` 添加`django_hosts.middleware.HostsRequestMiddleware`在`MIDDLEWARE`最前面;添加`django_hosts.middleware.HostsResponseMiddleware`在`MIDDLEWARE`最后面。 ```python # DjangoHostsTest/settings.py MIDDLEWARE = [ 'django_hosts.middleware.HostsRequestMiddleware', # django-hosts 必须添加到最前面(第2步) 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django_hosts.middleware.HostsResponseMiddleware', # django-hosts 必须添加到最后面(第3步) ] ``` 在项目主 urls.py 旁创建`hosts.py` 文件,创建一个包含默认主机模式的新模块 ![BLOG_20190521_154838_98](/media/blog/images/2019/05/BLOG_20190521_154838_98.png "博客图集BLOG_20190521_154838_98.png") 设置 `ROOT_HOSTCONF` 包含`hosts.py`文件的模块 ```python # DjangoHostsTest/settings.py ROOT_HOSTCONF = 'DjangoHostsTest.hosts' # django-hosts 在ROOT_URLCONF之后增加,指定hosts.py文件可引用位置(第4步) ``` 设置`DEFAULT_HOST`,没匹配到的就用该模式 ```python # DjangoHostsTest/settings.py DEFAULT_HOST = 'www' # django-hosts ROOT_HOSTCONF之后增加,设置默认模式匹配。如果没有其他模式匹配,或者没有为host_url模板标记指定名称,则将使用它。(第5步) ``` 设置`PARENT_HOST`显示域部分 ```python # DjangoHostsTest/settings.py PARENT_HOST = 'mydomain.cn' # django-hosts 如果想在呈现的URL的域部分附加一个默认域名,否则就只有“blog/index/”,而不是“blog.domain.cn/index/”(第6步) ``` ### 配置hosts.py ```python # DjangoHostsTest/hosts.py """ 创建一个包含默认主机模式的新模块,例如在url .py旁边的hosts.py文件中。 """ from django.conf import settings from django_hosts import patterns, host host_patterns = patterns('', # 配置模式的正则表达式,如果要使用https,在需要的host中增加 scheme='https://' 属性(第7步) host(r'www', settings.ROOT_URLCONF, name='www'), # http://www.domain.cn/ 直接请求主urls中配置的路由 host(r'api', 'api.urls', name='api'), # http://api.mydomain.cn/ host(r'blog', 'blog.urls', name='blog'), # http://blog.mydomain.cn/ ) ``` 此时刷新 http://blog.mydomain.cn/ 是会报错的 > `django.urls.exceptions.NoReverseMatch: 'blog' is not a registered namespace` ### 配置html 在模板中,可以使用`host_url()`template tag来反向使用Django的URL template tag,需要添加`{% load hosts %}` - BLOG主页 ```html <!-- apps/blog/templates/blog/index.html --> <!DOCTYPE html> {% load hosts %} <html lang="en"> <head> <meta charset="UTF-8"> <title>BLOG主页</title> </head> <body> <h2>BLOG主页</h2> {#<a href="{% url 'blog:list' %}">进入BLOG列表</a>#} <h4><a href="{% host_url 'list' host 'blog' %}">进入BLOG列表(django-hosts)</a></h4> </body> </html> ``` 就不能使用`<a href="{% url 'blog:list' %}">进入BLOG列表</a>`,这会导致报错。 > 注意:任何与该App有关的用过`host_url`的模板中,都不能出现Django中的`url`,否则会出现问题`'app' is not a registered namespace` ![BLOG_20190521_154811_72](/media/blog/images/2019/05/BLOG_20190521_154811_72.png "博客图集BLOG_20190521_154811_72.png") 现在BLOG列表的链接就是`http://blog.mydomain.cn/list/` - BLOG列表 ```html <!-- apps/blog/templates/blog/list.html --> <!DOCTYPE html> {% load hosts %} <html lang="en"> <head> <meta charset="UTF-8"> <title>BLOG列表</title> </head> <body> <h2>BLOG列表</h2> {#<h4><a href="{% url 'blog:index' %}">返回BLOG主页</a></h4>#} <h4><a href="{% host_url 'index' host 'blog' %}">返回BLOG主页(django-hosts)</a></h4> <ul> {# <li><a href="{% url 'blog:detail' 1 %}">进入BLOG详情1</a></li>#} {# <li><a href="{% url 'blog:detail' 2 %}">进入BLOG详情2</a></li>#} <li><a href="{% host_url 'detail' 1 host 'blog' %}">进入BLOG详情1(django-hosts)</a></li> <li><a href="{% host_url 'detail' 2 host 'blog' %}">进入BLOG详情2(django-hosts)</a></li> </ul> </body> </html> ``` ![BLOG_20190521_154749_97](/media/blog/images/2019/05/BLOG_20190521_154749_97.png "博客图集BLOG_20190521_154749_97.png") 如果是需要传递参数`<li><a href="{% url 'blog:detail' 1 %}">进入BLOG详情1</a></li>`,也要做类似的改动`<li><a href="{% host_url 'detail' 1 host 'blog' %}">进入BLOG详情1(django-hosts)</a></li>` 现在BLOG详情的链接就是`http://blog.mydomain.cn/detail/1/` - BLOG详情 ```html <!-- apps/blog/templates/blog/detail.html --> <!DOCTYPE html> {% load hosts %} <html lang="en"> <head> <meta charset="UTF-8"> <title>BLOG详情</title> </head> <body> <h2>BLOG详情</h2> {#<h4><a href="{% url 'blog:list' %}">返回BLOG列表</a></h4>#} <h4><a href="{% host_url 'list' host 'blog' %}">返回BLOG列表(django-hosts)</a></h4> <b>BLOG正文:</b> 当前访问的ID:{{ blog_id }} </body> </html> ``` ![BLOG_20190521_154735_79](/media/blog/images/2019/05/BLOG_20190521_154735_79.png "博客图集BLOG_20190521_154735_79.png") ### 视图中反向url 在Python方面,比如视图,类似于Django的单向函数。只需使用django_hosts中的`reverse()`函数 ```python # apps/blog/views.py from django.shortcuts import render from django_hosts.resolvers import reverse def index(request): blog_99_url = reverse('detail', args=(99,), host='blog') return render(request, 'blog/index.html', {'blog_99_url': blog_99_url}) ``` 在模板中显示该url ```html <!-- apps/blog/templates/blog/index.html --> <!DOCTYPE html> {% load hosts %} <html lang="en"> <head> <meta charset="UTF-8"> <title>BLOG主页</title> </head> <body> <h2>BLOG主页</h2> {#<a href="{% url 'blog:list' %}">进入BLOG列表</a>#} <h4><a href="{% host_url 'list' host 'blog' %}">进入BLOG列表(django-hosts)</a></h4> <a href="{{ blog_99_url }}" target="_blank">推荐阅读 {{ blog_99_url }}</a> </body> </html> ``` ![BLOG_20190521_154717_23](/media/blog/images/2019/05/BLOG_20190521_154717_23.png "博客图集BLOG_20190521_154717_23.png") 得到`blog_99_url`的连接为http://blog.mydomain.cn/detail/99/ 点进去就可以得到 ![BLOG_20190521_154657_52](/media/blog/images/2019/05/BLOG_20190521_154657_52.png "博客图集BLOG_20190521_154657_52.png") ### media文件加载404问题 修改原App urls.py ```python # blog urls apps/blog/urls.py from django.conf import settings from django.conf.urls.static import static from django.urls import path from .views import index, blog_list, blog_detail app_name = 'blog' urlpatterns = [ path('', index, name='index'), path('list/', blog_list, name='list'), path('detail/<str:blog_id>/', blog_detail, name='detail'), ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ``` 当DEBUG模式时,增加media的路径,而不用hosts时,media是配置到项目主 urls.py 中的 > Nginx的配置只需要将子域名都绑定到对应的启动端口即可,后端根据子域名进行不同的路由。 > 另外这也会存在跨域问题,比如`http://blog.mydomain.cn/`登录是在`http://www.mydomain.cn/usercenter/login/`这个链接。

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行2285天
  • 系统信息:Linux
  • 后台程序:Python: 3.8.10
  • 网站框架:Django: 3.2.6
  • 文章统计:257 篇
  • 文章评论:63 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站