Fork me on GitHub

2.Django|简介与静态文件| URL控制器

 1、简介

 MVC

  Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求。

 

MTV

  Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:

M 代表模型(Model):负责业务对象和数据库的关系映射(ORM)。

T 代表模板 (Template):负责如何把页面展示给用户(html)。

V 代表视图(View):负责业务逻辑,并在适当时候调用Model和Template。

除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示

  一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

下载安装创建 (2.0以上版本与1.0版本还是差别挺大的)

pip3 install django=2.0.1

查看安装到哪里了呢

创建一个Django项目(在终端里边,在pycharm里边创建)

django-admin.py startproject mysite

当前目录下会生成mysite的工程,目录结构如下:

        

  • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等,与Django交互。
  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
  • urls.py ----- 负责把URL模式映射到应用程序。

在mysite目录下创建应用

python manage.py startapp blog
python manage.py startapp app01 #创建第二个应用

启动django项目

python manage.py runserver 8080  #默认本机的8080端口,也可以是其他端口

 

 

 

 在pycharm里边创建

 

2.静态文件配置

Django文件 :demo 

 

如果是报这样一个错:

Failed to load resource: the server responded with a status of 404 (Not Found)

则是没有配置静态文件路径,加上上边 STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"),]  即可。 

这样设置完之后就可以访问到了http://127.0.0.1:8000/static/jquery-3.2.1.js      从路径URL中配置static,然后找到文件夹下的static文件。

所有的静态文件都在static里边

 css、js都写到静态文件里边

views.py

from django.shortcuts import render

# Create your views here.

def timer(request):
    import time
    ctime = time.time()
    return render(request, "ctime.html", {"ctime":ctime}) 

 render方法就是去渲染一个方法,帮我们去找templates下面的文件,读出数据返回;同时它还把这个ctime变量嵌套到了ctime.html这个页面中了

{{"ctime": ctime}} ,{ { } } 就是一种特殊语法,把视图函数里边的变量传到html页面中

templates/ctime.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
{#    <style>#}
{#        h4{#}
{#            color: red;#}
{#        }#}
{#    </style>#}
    <script src="/static/jquery-3.2.1.js"></script>  {# 客户端浏览器执行的时候它找不到这个文件,得配置一个static路径 #}
    <link rel="stylesheet" href="/static/app01/timer.css">
</head>
<body>
    <h4>hi当前时间为:{{ ctime }}</h4>
<script src="/static/app01/timer.js"></script>
</body>
{#    <script>#}
{#        $('h4').click(function () {#}
{#            $(this).css("color","green")#}
{#        })#}
{#    </script>#}
</html>

static/app01/ timer.css

h4{
    color: red;
}

static/app01/timer.js

$('h4').click(function () {
            $(this).css("color","green")
})

 

 

  整个流程:用户输入http://127.0.0.1:8000/timer/交给URL控制器(控制行为),匹配到就执行timer视图函数(一旦匹配成功,path这个函数方法帮你去调这个匹配到的函数,调的时候就会给你传一个request参数,所有的请求信息数据都封装在了request里边),这个视图函数在app01里的views里边找到timer方法(timer方法做逻辑处理);取出来一个叫ctimer(之前我们是open这个文件然后再返回,现在通过一个render方法把这所有的事情都做了。)

3、Django-2的路由层

   URL配置(URLconf)就像django所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表,你就是以这种方式告诉django,对于客户端发来的某个RUL调用哪一段逻辑代码对应执行。

 django文件 first_pro 

3.1简单的路由配置

re_path是1.0版本的,path是2.0版本的,2.0既支持1.0的又支持它自己特殊的语法

import re

re.search(匹配规则,待匹配项);^是以什么开头,$是以什么结尾;

re.search(

'^articles/2003/$',articles/2003/(必须输入这个了就)

)

^articles/([0-9]{4})/$是分组匹配,如articles/2008(路径匹配和视图函数是多对一的关系;)
^articles/([0-9]{4})/([0-9]{2})/$ 如articles/2008/12
^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$
from django.contrib import admin
from django.urls import path, re_path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)

    #路由配置:   路径 -----> 视图函数
    re_path(r'^articles/2003/$', views.special_case_2003),  #special_case_2003(request)
    re_path(r'^articles/([0-9]{4})/$', views.year_archive), #year_archive(request,1999) 传几个参数就要接收几个参数;跟视图函数是多对一;须严格限定住以它开头以它结尾,不要等它匹配完就不走下一步了
    re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), #month_archiverequest,199912)
    # re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),


]

 HttpResponse是响应对象,是要写字符串的在这里一定定义的是响应体。响应头、响应首行已经被Django的wsgiref处理了;你想在这个页面中看什么内容,就在

HttpResponse里边写什么内容就可以了。

from django.shortcuts import render,HttpResponse

# Create your views here.

def timer(request):    #这个是逻辑行为,逻辑行为直接找到这个文件
    import time
    ctime = time.time()
    return render(request, "timer.html", {"date":ctime})  #render方法,由它去找这个文件;不需要写路径,它会自己找
                                                        #render找到这个html,打开取出这里边的数据,同时把这个变量嵌套在那个位置

def special_case_2003(request):

    return HttpResponse("special_case_2003")

def year_archive(request, year):
    return HttpResponse(year)

def month_archive(request, year, month):
    return HttpResponse(year + "-" + month )

注意:

  • 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles
  • 每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义

 

3.2有名分组

(可以避免两个url中所匹配的项混淆,代码是从上往下执行的,就先匹配上边匹配到的,如果下面的utl也匹配到了就不再走了,可以使用^和$)

  上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

下面是以上URLconf 使用命名组的重写:

from django.urls import path,re_path

from app01 import views

urlpatterns = [                                                                          #这里边传了几个参数,相对应的视图函数就要传几个参数。
    re_path(r'^articles/2003/$', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),                      #year_archive(request,year=2009)
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), #year_archive(request,year=1028,month=12)
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), #(request,year=2018,month=08,day=08)
]
re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$', views.month_archive), #month_archive(request,y=1999,m=12);这里边传了3个参数,视图函数就要接收3个参数

相对应的视图函数 ------->>>
def month_archive(request,m, y):  #把它位置捣乱,就乱了;可以给每个组起个名字固定住;一定要按关键字来,是那个名字;这里形参必须是m 和 y,不能写成month或者year
    print(m)  #12
    print(type(m))
    print(y)
    print(type(y))
    #m = int(m)

    return HttpResponse(y + "-" + m )

 

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。

在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;

3.3路由分发

全局不应该写url,它应做分发。

 把全局的urls.py复制到app01的应用里边一份,然后把全局的path那部分给删掉。全局里边(也就是first_pro里边的urls)的针对app01的re_path给删掉。

appo1/urls.py(app01里边的)

from django.contrib import admin
from django.urls import path, re_path

from app01 import views

urlpatterns = [
    #路由配置:   路径 -----> 视图函数
    re_path(r'^articles/2003/$', views.special_case_2003),  #special_case_2003(request)
    re_path(r'^articles/([0-9]{4})/$', views.year_archive), #year_archive(request,1999) 传几个参数就要接收几个参数;跟视图函数是多对一;须严格限定住以它开头以它结尾,不要等它匹配完就不走下一步了
    # re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), #month_archive(request,199912)
    re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$', views.month_archive), #month_archive(request,y=1999,m=12);这样函数的形参就可以颠倒位置了
    # re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

first_pro/urls.py(全局的)

from django.contrib import admin
from django.urls import path, re_path, include

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)
    path('login',views.login),

    #f分发 每个url单独写到自己的app里边去,在全局做分发就可以了,实现了解耦;
    # re_path(r"app01/", include("app01.urls")),#如浏览器中输入,前面就必须加app01了http://127.0.0.1:8000/app01/articles/2003/04
    re_path(r"^", include("app01.urls")),       #浏览器中就可以不写app01了
   re_path(r"app02/",include("app02.urls")), ]

app01 views.py

from django.shortcuts import render,HttpResponse

# Create your views here.

def timer(request):    #这个是逻辑行为,逻辑行为直接找到这个文件
    import time
    ctime = time.time()
    return render(request, "timer.html", {"date":ctime})  #render方法,由它去找这个文件;不需要写路径,它会自己找
                                                        #render找到这个html,打开取出这里边的数据,同时把这个变量嵌套在那个位置
def special_case_2003(request):
    return HttpResponse("special_case_2003")

def year_archive(request, year):
    return HttpResponse(year)

def month_archive(request,y, m):  #把它位置捣乱,就乱了;可以给每个组起个名字固定住;一定要按关键字来,是那个名字
    return HttpResponse(y + "-" + m )

def login(request):
    return render(request, "login.html")

   

 3.4路由控制之登录验证

views.py

def login(request):
    print(request.method)
    if request.method == "GET":
        return render(request, "login.html")
    else:
        print(request.GET)
        print(request.POST)
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "kris" and pwd == "123":
            return HttpResponse("登录成功")
        else:
            return HttpResponse("用户名或密码错误")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://127.0.0.1:8000/login" method="post"> ##如果不加,就默认是当前页面的网址,/login要加,login要跟url路由里边对应好了
        用户名 <input type="text" name="user"> 
        密码   <input type="password" name="pwd">
        <input type="submit">

    </form>
</body>
</html>

 

[12/Aug/2018 16:15:18] "GET /login.html/ HTTP/1.1" 200 316
GET
POST
<QueryDict: {}>
<QueryDict: {'user': ['kris'], 'pwd': ['abc']}>
[12/Aug/2018 16:15:45] "POST /login.html/ HTTP/1.1" 200 24

3.5反向解析

path('login.html/',views.login, name="log"),如果我们在起名字的时候写成了login.html,那么用户在访问的时候就要访问http://127.0.0.1:8000/login.html/,那么
--------------->>>>
<form action="http://127.0.0.1:8000/login" method="post"> {# 你这里边写的是login,那么提交post请求的时候就会报错了#} 用户名 <input type="text" name="user"> 密码 <input type="password" name="pwd"> <input type="submit"> </form>

模板语法只有2个:一个是{{}},另外一个就是{% %}

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <form action="{% url 'log' %}" method="post">{#刚刚我们把它写死了;模板语法之一,render在渲染这个html页面的过程中,它会去解析这个html页面,解析到{% url 'log' %}
的时候它就反向解析;它要去全局里边找一个叫log的name,找到之后取出来渲染之后替换{% url 'log' %}这部分内容,然后再发给客户端的浏览器#} 用户名 <input type="text" name="user"> 密码 <input type="password" name="pwd"> <input type="submit"> </form> </body> </html>

 

from django.contrib import admin
from django.urls import path, re_path, include

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)
    path('login.html/',views.login, name="log"), #给它起的别名,login可能会变,但这个log别名不变

    #f分发
    # re_path(r"app01/", include("app01.urls")),
    re_path(r"^", include("app01.urls")),#浏览器中可以不写app01了

]

 

流程

如果urlpatterns里边的路径path改为login.html/,其他地方都不需要改动。用户在浏览器中输入http://127.0.0.1:8000/login.html/时,得到的页面,它访问的在视图里边,视图里边再渲染login.html(return render(request,"login.html")),渲染它的过程中在 <form action="{% url 'log' %}" method="post">中取log,拿到 name="log",

path('login.html/',views.login, name="log"),改完之后把login.html拿到action中。

不在模板里边,在视图里边进行反向解析,在python里边

#Author:Kris  #app01/urls.py

from django.contrib import admin
from django.urls import path, re_path

from app01 import views

urlpatterns = [
    #路由配置:   路径 -----> 视图函数
    re_path(r'articles/2003/$', views.special_case_2003, name="s_c_2003"),  #special_case_2003(request);它是一个完整的,没有正则
    re_path(r'^articles/([0-9]{4})/$', views.year_archive, name="y_a"), #year_archive(request,1999) 传几个参数就要接收几个参数;跟视图函数是多对一;须严格限定住以它开头以它结尾,不要等它匹配完就不走下一步了
    # re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), #month_archive(request,199912)
    re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$', views.month_archive), #month_archive(request,y=1999,m=12);这样函数的形参就可以颠倒位置了
    # re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

 

from django.shortcuts import render,HttpResponse

# Create your views here.

def timer(request):    #这个是逻辑行为,逻辑行为直接找到这个文件
    import time
    ctime = time.time()

    url = reverse("s_c_2003")
    url = reverse("y_a", args=(1234, )) #/articles/([0-9]{4})/
    print(url)  #先从全局里边找,没有再去局部里边找,有个name="s_c_2003".

    return render(request, "timer.html", {"date":ctime})  #render方法,由它去找这个文件;不需要写路径,它会自己找
                                                        #render找到这个html,打开取出这里边的数据,同时把这个变量嵌套在那个位置

from django.urls import reverse

def special_case_2003(request):
    # url = reverse("s_c_2003")  反向解析
    # url = reverse("y_a", args=(234, )) #你解析出来的是这个app01/articles/([0-9]{4})/ 需要给它加个参数,任何4位数字都可以以替换符合正则表达式,反向解析出来的不含正则,
    # print(url)  #先从全局里边找,没有再去局部里边找,有个name="s_c_2003";它写到哪个视图函数下面是无所谓的,它利用的是reverse这个函数

    return HttpResponse("special_case_2003")

def year_archive(request, year):
    return HttpResponse(year)

/articles/1234/
[26/May/2018 09:33:22] "GET /articles/2003/ HTTP/1.1" 200 17
[26/May/2018 09:33:28] "GET /articles/2009 HTTP/1.1" 301 0
[26/May/2018 09:33:28] "GET /articles/2009/ HTTP/1.1" 200 4

/articles/1234/ # 你得访问timer,才能打印出来它了,即反向解析出来的。用任意4位数字来替换正则表达式子的,它不会给你解析出正则的,只能是4位数字
[26/May/2018 09:44:08] "GET /timer/ HTTP/1.1" 200 164

跟当前访问的路径没有关系,只是给它反向解析了,给我一个别名就可以解析出这个url,它含正则表达式,就可以通过参数来进行匹配替换从而拿到一个固定的url

 

 3.6名称空间

创建app02

  命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。

 first_pro\urls

from django.contrib import admin
from django.urls import path, re_path, include

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)
    path('login.html/',views.login, name="log"), #给它起的别名,login可能会变,但这个log别名不变

    #f分发
    # re_path(r"app01/", include("app01.urls")),
    re_path(r"^app01", include(("app01.urls", "app01"))),#只写这个r"^"浏览器中可以不写app01了
    re_path(r"^app02", include(("app02.urls", "app02"))), #在元组里边给它加上个名称空间app01、app02,起个房间号,名称空间。
]

app01\views

from django.urls import reverse

def index(request):
    return HttpResponse(reverse('app01:index')) #你要反向解析哪个index,在前面加上'app01'

app02\views

from django.urls import reverse

def index(request):
    return HttpResponse(reverse('app02:index'))#在前面加上'app02'

app01\urls

from django.contrib import admin
from django.urls import path, re_path

from app01 import views

urlpatterns = [
     re_path("index/", views.index, name="index")
]

app02\urls

from django.contrib import admin
from django.urls import path, re_path

from app02 import views
urlpatterns = [
    re_path("index/", views.index, name="index")

]

    

3.7控制器之django2.0的path

考虑下这样的两个问题:

第一个问题,函数 year_archive 中year参数是字符串类型的,因此需要先转化为整数类型的变量值,当然year=int(year) 不会有诸如如TypeError或者ValueError的异常。那么有没有一种方法,在url中,使得这一转化步骤可以由Django自动完成?

第二个问题,三个路由中article_id都是同样的正则表达式,但是你需要写三遍,当之后article_id规则改变后,需要同时修改三处代码,那么有没有一种方法,只需修改一处即可?

在Django2.0中,可以使用 path 解决以上的两个问题。

 re_path(r'^articles/([0-9]{4})/$', views.year_archive, name="y_a"), #year_archive(request,1999) 
#其实我们传的1999是个字符串str而不是int类型#year_archive(request,'1999')

 

first_pro\urls

from django.contrib import admin
from django.urls import path, re_path, include

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)
    path('login.html/',views.login, name="log"), #给它起的别名,login可能会变,但这个log别名不变

    #f分发
    # re_path(r"app01/", include("app01.urls")),
    re_path(r"^app01", include(("app01.urls", "app01"))),#只写这个r"^"浏览器中可以不写app01了
    #re_path(r"^app02", include(("app02.urls", "app02"))), #在元组里边给它加上个名称空间app01、app02

    path("articles/<int:year>", views.path_year) #匹配数字,浏览器默认发的是字符串;path_year(request,2001)
    #path("articles/<path:year>", views.path_year) #只要非空就可以了,?不行,?=1get请求时把它作为了分隔匹配的内容了
]

 

app01\views

def year_archive(request, year):
    return HttpResponse(year)

def month_archive(request,m, y):  #把它位置捣乱,就乱了;可以给每个组起个名字固定住;一定要按关键字来,是那个名字
    print(m)  #12
    print(type(m))
    print(y)
    print(type(y))
    m = int(m)

    return HttpResponse(y + "-" + m )

def path_year(request, year): 
    print(year)
    print(type(year))

    return HttpResponse("path year")

2000
<class 'int'>
[26/May/2018 11:18:37] "GET /articles/2000 HTTP/1.1" 200 9

 

基本规则:

  • 使用尖括号(<>)从url中捕获值。
  • 捕获值中可以包含一个转化器类型(converter type),比如使用 <int:name> 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
  • 无需添加前导斜杠。

 

 

path转化器

文档原文是Path converters,暂且翻译为转化器。

Django默认支持以下5个转化器:

  • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
  • int,匹配正整数,包含0。
  • slug,匹配字母、数字以及横杠、下划线组成的字符串。
  • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path,匹配任何非空字符串,包含了路径分隔符

自定义转换器

5个内置的转换器太少了,可以自己定义。

对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:

  • regex 类属性,字符串类型
  • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
  • to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。

 新建一个py文件  urlconvert.py

class MonConvert:
    regex = "[0-9]{2}" #规则,0-9的2个数字
    def to_python(self, value):
        return int(value)  #把这个value作为参数传进去
    def to_url(self, value): #用于反向解析的时候
        return '%04d'% value

first_pro\urls

from django.contrib import admin
from django.urls import path, re_path, include, register_converter

from app01.urlconvert import MonConvert
register_converter(MonConvert, "mm") #注册自定义的url转换器,起个名字mm(2位的数字),到时候替换

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('timer/', views.timer),  #控制行为找到这个视图函数,一旦匹配成功之后,就会传一个request的信息,浏览器中发生的请求信息都在这里边;views.timer(request)
    path('login.html/',views.login, name="log"), #给它起的别名,login可能会变,但这个log别名不变

    #path("articles/<path:year>", views.path_year), #只要非空就可以了,?不行,?=1get请求时把它作为了分隔匹配的内容

    path("articles/<mm:month>", views.path_month),
]

app01\views

def path_year(request, year):
    print(year)
    print(type(year))

    return HttpResponse("path year")

def path_month(request, month):
    print(month, type(month))
    return HttpResponse("path month。。。")

3 <class 'int'>
[26/May/2018 12:04:09] "GET /articles/03 HTTP/1.1" 200 19
34 <class 'int'>
[26/May/2018 12:04:27] "GET /articles/34 HTTP/1.1" 200 19

 

4总结:

django的第一站就是,在url中进行路径匹配,匹配成功了就会执行视图

 正则、分组、有名分组、分发做解耦用的、反向解析、名称空间(避免重名)

 

posted @ 2018-05-27 15:56  kris12  阅读(812)  评论(0编辑  收藏  举报
levels of contents