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/ 保持不变

项目结构


基础配置

# blogs/settings.py

ALLOWED_HOSTS = [

    '.mydomain.cn',  # 匹配.mydomain.cn的所有域名

]

修改主机的hosts,以支持域名访问本地服务,且服务运行在80端口run server 0.0.0.0:80测试。

127.0.0.1 www.mydomain.cn

127.0.0.1 blog.mydomain.cn

127.0.0.1 api.mydomain.cn

项目主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

from django.urls import path

from .views import index

app_name = 'www'

urlpatterns = [

    path('', index, name='index'),

]

<!-- 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 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'),

]

<!-- apps/blog/templates/blog/index.html -->

<h2>BLOG主页</h2>

<a href="{% url 'blog:list' %}">进入BLOG列表</a>

<!-- 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>

<!-- apps/blog/templates/blog/detail.html -->

<h2>BLOG详情</h2>

<h4><a href="{% url 'blog:list' %}">返回BLOG列表</a></h4>

<b>BLOG正文:</b>

当前访问的ID:{{ blog_id }}

django-hosts配置

实现 http://www.mydomain.cn/blog/ --> http://blog.mydomain.cn/

现在如果直接访问 http://blog.mydomain.cn/ 是显示的项目主页,因为没有具体路径的url都由path('', include('www.urls', namespace='www')),去匹配

安装

pip install django-hosts

配置settings.py

添加 django_hosts 到 INSTALLED_APPS

# blogs/settings.py

INSTALLED_APPS = [

    ......

    'django_hosts',  # pip install django-hosts 安装,添加app(第1步)

    ......

]

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步)

]

在主项目下创建hosts.py 文件,创建一个包含默认主机模式的新模块

第4步,在ROOT_URLCONF之后增加,指定hosts.py文件可引用位置,设置 ROOT_HOSTCONF 包含hosts.py文件的模块

# blogs/settings.py

ROOT_HOSTCONF = 'blogs.hosts' 

第5步,设置DEFAULT_HOST,没匹配到的就用该模式,django-hosts  ROOT_HOSTCONF之后增加,设置默认模式匹配。如果没有其他模式匹配,或者没有为host_url模板标记指定名称,则将使用它。

# blogs/settings.py

DEFAULT_HOST = 'www'

第6步设置PARENT_HOST显示域部分,如果想在呈现的URL的域部分附加一个默认域名,否则就只有“blog/index/”,而不是“blog.domain.cn/index/”

# blogs/settings.py

PARENT_HOST = 'mydomain.cn'

配置hosts.py

# blogs/hosts.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主页

<!-- apps/blog/templates/blog/index.html -->

{% load hosts %}

<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="{% url 'blog:list' %}">进入BLOG列表</a>,这会导致报错。

注意:任何与该App有关的用过host_url的模板中,都不能出现Django中的url,否则会出现问题'app' is not a registered namespace

现在BLOG列表的链接就是http://blog.mydomain.cn/list/

●BLOG列表

<!-- apps/blog/templates/blog/list.html -->

{% load hosts %}

<h4><a href="{% host_url 'index'  host 'blog' %}">返回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>#}

    <li><a href="{% host_url 'detail' 1  host 'blog' %}">进入BLOG详情1</a></li>

    <li><a href="{% host_url 'detail' 2  host 'blog' %}">进入BLOG详情2</a></li>

</ul>

如果是需要传递参数<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详情

<!-- apps/blog/templates/blog/detail.html -->

{% load hosts %}

<h2>BLOG详情</h2>

<h4><a href="{% host_url 'list' host 'blog' %}">返回BLOG列表</a></h4>

<b>BLOG正文:</b>

当前访问的ID:{{ blog_id }}

视图中反向url

在Python方面,比如视图,类似于Django的单向函数。只需使用django_hosts中的reverse()函数

# 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

<!-- 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_99_url的连接为http://blog.mydomain.cn/detail/99/

点进去就可以得到

media文件加载404问题

修改原App urls.py

# 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/这个链接。

https://github.com/fungitive/blogs-domian 

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容