zoukankan      html  css  js  c++  java
  • 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_prourls

    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,起个房间号,名称空间。
    ]

    app01views

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

    app02views

    from django.urls import reverse
    
    def index(request):
        return HttpResponse(reverse('app02:index'))#在前面加上'app02'

    app01urls

    from django.contrib import admin
    from django.urls import path, re_path
    
    from app01 import views
    
    urlpatterns = [
         re_path("index/", views.index, name="index")
    ]

    app02urls

    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_prourls

    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请求时把它作为了分隔匹配的内容了
    ]

    app01views

    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_prourls

    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),
    ]

    app01views

    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中进行路径匹配,匹配成功了就会执行视图

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

  • 相关阅读:
    protected、public、private
    第十五章 面向对象程序设计
    第十四章 重载运算与类型转换
    聚合类
    explicit构造函数
    allocator类
    直接管理内存——new和delete
    智能指针
    Bugku-CTF之点击一百万次
    Bugku-CTF之flag在index里
  • 原文地址:https://www.cnblogs.com/shengyang17/p/9090136.html
Copyright © 2011-2022 走看看