zoukankan      html  css  js  c++  java
  • Django(二)路由系统、视图、模板

    大纲

    一、内容概要: 
    二、上节回顾 
    三、Django 视图–views 
      1、获取用户多个数据及文件上传 
      2、FBV 和 CBV 
      3、装饰器 
    四、Django模板补充 
      - Django模板语言循环字典 
    五、Django 路由系统 
      1、一对一:一个url对于一个函数或者一个类 
      2.1、一对多:一类url对应一个函数或者一个类 
      2.2、一对多,用法总结 
      3、name参数 
      4、url 路由分发机制 
      5、默认值 
      6、命名空间

    一、内容概要:

    1、路由系统——urls

    2、视图

    3、模板

    4、ORM操作

    ​ select * from tb where id > 1

    ​ # 对应关系

    ​ models.tb.objects.filter(id__gt=1)

    ​ models.tb.objects.filter(id=1)

    ​ models.tb.objects.filter(id__lt=1)

    二、上节回顾

    1、Django请求生命周期

        客户端 -> URL对应关系(匹配) -> 视图函数 -> 返回用户字符串
        客户端 -> URL对应关系(匹配) -> 视图函数 -> 打开一个HTML文件,读取内容
    • 1
    • 2

    2.1、创建django projcet

        django-admin startproject mysite
        ..
        mysite
            mysite
                - 配置文件
                - urls.py
                - settings.py
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2创建django project app

        cd mysite
        python manage.py startapp cmdb
    
        mysite
            mysite
                ……
            cmdb
                - views.py
                - admin.py
                - models.py # 创建数据库表
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3、配置

        模板路径
        静态文件路径
        # 注释 CSRF
    • 1
    • 2
    • 3

    4、编写程序

        a. url.py
    
            /index/    ->   func
    
        b. views.py
    
            def func(request):
                # request:包含所有的请求数据
                ...
                return HttpResponse('字符串')  # 返回字符串
                return render(request, 'index.html', {''})  # 返回模板内容
                retrun redirect('URL')  # 返回url
    
        c. 模板语言
            return render(request, 'index.html', {'li': [11,22,33]})
    
            {% for item in li %}  # 模板语音for循环
                <h1>{{item}}</h1>
            {% endfor %}
    
        ***********  去索引:索引用点 **********
            <h2> {{item[0] }} </h2>  # 不能这么用,
            <h2> {{item.0 }} </h2>   # 正确写法
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    三、Django 视图–views

    1、获取用户多个数据及文件上传

    • 1、获取用户请求数据
    request.GET     # 获取相应信息中get发送的数据
    request.POST    # 获取相应信息中post发送的数据
    request.FILES   # 获取相应信息中发送的文件数据
    PS: # get和post都是往后台发送数据,只是get信息在网址中,post信息包含着数据内,往往:
        GET:    # 获取数据              
        POST:   # 提交数据
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 2、checkbox等多选的内容
    request.POST.getlist()  # get只能获取一个值,像复选框、多选下拉框时,需要用getlist获取
    • 1
    • 3、上传文件
    # 上传文件,form标签做特殊设置  enctype="multipart/form-data"
    obj = request.FILES.get('fafafa')  # 获取上传文件对象
    print( obj.name )  # 上传文件名称
    f = open(obj.name, mode='wb')
    for item in obj.chunks():  # chunks():分块,一点一点取数据(生成器、迭代器)
    f.write(item)
    f.close()
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例:用户提交数据,后台接收响应数据,并进行处理

    工程名:mysite,app名:cmdb,创建接收用户上传数据目录upload

    mysite/urls.py

    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
    ]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    cmdb/views.py

    from django.shortcuts import render, redirect,HttpResponse
    
    def login(request):
        if request.method == "GET":
            return render(request, 'reg.html')
        elif request.method == "POST":
            # redio 单选框获取
            redio = request.POST.get("gender")
            print("单选框的值:", redio)
            # checkbox 复选框获取
            checkbox = request.POST.getlist("favor")
            print("复选框的值", checkbox)
            # 获取文件数据
            obj = request.FILES.get("fafafa")
            print(obj, type(obj), obj.name)  # 打印文件信息
            import os
            file_path = os.path.join('upload', obj.name)
            with open (file_path, mode="wb") as f:
                for i in obj.chunks():
                    f.write(i)
            return render(request, "reg.html")
        else:
            # PUT, DELETE, HEAD, OPTION……
            return redirect("/reg/")
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    templates/reg.html

    <body>
        <form action="/login/" method="POST" enctype="multipart/form-data">
            <p>
                <input type="text" name="user" placeholder="用户名" />
            </p>
            <p>
                <input type="password" name="pwd" placeholder="密码" />
            </p>
            <p>性别:
                男:<input type="radio"  name="gender" value="1"/>
                女:<input type="radio" name="gender" value="2"/>
            </p>
            <p>爱好:
                男:<input type="checkbox"  name="favor" value="11"/>
                女:<input type="checkbox" name="favor" value="22"/>
            </p>
            <p>
                <select name="city" multiple>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="tj">天津</option>
                </select>
            </p>
            <p>
                <input type="file" name="fafafa"/>
            </p>
            <input type="submit" value="提交"/>
        </form>
    </body>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2、FBV 和 CBV

    像这种urls.py里匹配login,之后对应一个函数名。当匹配成功之后,就 执行views.py里的这个函数,函数里第一个参数封装了所有的用户请求信息。像这种叫FBV(function base view)

    Django 里面还有一种:CBV(class base view)

    /index/ -> 函数名 
    /index/ -> 类

    上面都是FBV的方式,下面看看CBV写法:

    urls.py

        url(r'^home/', views.Home.as_view()),  # CBV 固定用法
    • 1

    views.py

    from django.views import View
    
    class Home(View):  # 自定义的类必须继承View
        # 重写父类dispatch方法。程序定制时可以使用
        # 父类的dispatch方法,查找get、post等方法,基于反射实现的。
        def dispatch(self, request, *args, **kwargs):
            print("类似装饰器:before")
            result = super(Home,self).dispatch(request, *args, **kwargs)
            print("类似装饰器:after")
            return result
    
        def get(self,request):  # 定义get方法,get请求执行这个方法
            print(request.method)
            return render(request, "home.html")
    
        def post(self,request):  # 定义post方法,post请求执行这个方法
            print(request.method,"post方式")
            return render(request, "home.html")
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    home.html

    <body>
        <form action="/home/" method="POST">
            <input type="text" name="user" />
            <input type="submit" />
        </form>
    </body>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、装饰器

    后续文章补充

    四、Django模板补充

    - Django模板语言循环字典

    urls.py

    url(r'^index/', views.index),
    • 1

    views.py

    USER_DICT = {
        'key1':{'name':'root1','eamil':'root@126.com'},
        'key2':{'name':'root2','eamil':'root@126.com'},
        'key3':{'name':'root3','eamil':'root@126.com'},
    }
    def index(request):
        return render(request, 'index.html', {'user_dict': USER_DICT})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    index.html

    <body>
        {{ user_dict.k1 }}
        <ul>
        {#  for row in user_dict # 默认循环显示的是key  #}
            {% for k in user_dict.keys %}  {# 循环字典:取key值 #}
                <li>{{ k }}</li>
            {% endfor %}
        </ul>
        <ul>
            {% for val in user_dict.values %}  {# 循环字典:取value值 #}
                <li>{{ val }}</li>
            {% endfor %}
        </ul>
        <ul>
            {% for k,row in user_dict.items %}  {# 循环字典:取key、value #}
                <li>{{ k }}-{{ row }}</li>
            {% endfor %}
        </ul>
    </body>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    五、Django 路由系统

    1、一对一:一个url对于一个函数或者一个类

        url(r'^index/', views.index),    
        url(r'^home/', views.Home.as_view()),
    • 1
    • 2

    2.1、一对多:一类url对应一个函数或者一个类

    如上循环字典的显示,如果是主机信息,应该显示主机名,点击才显示详细信息。实现如下:

    urls.py

        url(r'^index/', views.index),
        url(r'^detail-(keyd+).html/', views.detail),
    • 1
    • 2

    注意:这里网址实现的方式是类似http://127.0.0.1/detail-key1.html,而不是之前的detail?nid=key1的方式。这种方式,对于网站权重来说,搜索引擎更喜欢第一种方式。权重更好,会让搜索引擎以为网页是静态的。

    views.py

    USER_DICT = {
        'key1':{'name':'root1','eamil':'root@126.com'},
        'key2':{'name':'root2','eamil':'root@126.com'},
        'key3':{'name':'root3','eamil':'root@126.com'},
        'key4':{'name':'root4','eamil':'root@126.com'},
        'key5':{'name':'root5','eamil':'root@126.com'},
    }
    def index(request):
        return render(request, 'index.html', {'user_dict': USER_DICT})
    
    def detail(request, nid):
        # nid: url里正则二次过滤获取的值
        detail_info = USER_DICT[nid]
        return render (request, 'detail.html', {'detail_info': detail_info})
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    index.html

        <ul>
            {% for k,row in user_dict.items %}
                <li><a target="_blank" href="/detail-{{ k }}.html">{{ row.name }}</a></li>
            {% endfor %}
        </ul>
    • 1
    • 2
    • 3
    • 4
    • 5

    detail.html

    <body>
        <h1>详细信息</h1>
        <h6>用户名:{{ detail_info.name }}</h6>
        <h6>邮箱:{{ detail_info.email }}</h6>
    </body>
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2、一对多,用法总结

    • 上面的示例中,二次匹配一个值,多传一个形参匹配:

    urls.py:url(r'^detail-(keyd+).html/', views.detail),

    views.py:def detail(request, nid):

    访问网址:127.0.0.1/detail-key1.html

    • 如果再多匹配一个值,则如下:

    urls.py:url(r'^detail-(keyd+)-(d+).html/', views.detail),

    views.py:def detail(request, nid, uid):

    访问网址:127.0.0.1/detail-key1-9.html

    可见:url中二次匹配的值,和形参必须一一对应,但如果位置改了,里面的代码也得跟着改

    • 支持正则表达式 分组

    urls.py:url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html/', views.detail),

    直接第一个匹配的传递给nid,第二个匹配的传递给uid,这样和views里的函数形参位置没有关系了。

    views.py:def detail(request, nid, uid):

    访问网址:127.0.0.1/detail-key1-9.html

    • 分组时,个数不确定*args,**kwargs也能使用

    url(r'^detail-(keyd+)-(d+).html/', views.detail), ——> def detail(request, *args):

    url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html/', views.detail), ——> def detail(request, **kwargs):

    3、name参数

    如下内容:提交表单中action="/home/"需要跟着url中网址的修改而修改。

    home.html

        <form action="/home/" method="POST">
            <input type="text" name="user" />
            <input type="submit" />
        </form>
    • 1
    • 2
    • 3
    • 4

    urls.py

    url(r'^home/', views.home),
    • 1

    其他web框架也是这么实现的,要改两处都需要跟着修改。这里django给提供了一个便捷的用法,name参数。

    • name :django 简便用法

      对URL路由关系进行命名, 以后可以根据此名称生成自己想要的URL

    urls.py

    url(r'^home/', views.home, name="homeee"),
    • 1

    home.html

        <form action="{% url 'homeee' %}" method="POST">
            <input type="text" name="user" />
            <input type="submit" />
        </form>
    • 1
    • 2
    • 3
    • 4

    这样写上之后,url变了,只修改urls.py那里一处就可以了。

    • name :匹配地址里有分组的处理

    第二种:

    # urls.py
    url(r'^yug/(d+)/(d+)/', views.index, name='i2'),
    # views.py
    def index(request,nid,uid):
        ......
    • 1
    • 2
    • 3
    • 4
    • 5
    # html
    {% url "i2" 1 2 %}           # 成功匹配都,都跳转到: yug/1/2/
    • 1
    • 2

    第三种:

    # urls.py
    url(r'^buy/(?P<pid>d+)/(?P<nid>d+)/', views.index, name='i3'),  # # buy/1/9/
    • 1
    • 2
    # html
    {% url "i3" pid=1 nid=9 %}   # buy/1/9/
    • 1
    • 2

    上面是通过模板语音生成url,下面是通过reverse模块生成url,两种方式,实现功能一样。

    # views.py 文件
    def func(request, *args, **kwargs):
        from django.urls import reverse    #  根据名字反转生成一个url
        url1 = reverse('i1')                              # asdfasdfasdf/
        url2 = reverse('i2', args=(1,2,))                 # yug/1/2/
        url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    作用:用户完成某些操作后,跳转到指定页面。


    # 注:
    request.path_info   # 当前的url
    def index(request,nid):
        print(request.path_info)
        return render(request, 'index.html')
    
    <form action="{{ request.path_info }}" method="POST">
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、url 路由分发机制

    前面的urls对应关系都在urls.py内,如果多个app,都需要在这里引入。如果app多了,任何一个app的修改都会修改这一个urls文件。

    在django里面,有一个url分发的机制。

    urls.py

    from django.conf.urls import include
    urlpatterns = [
        url(r'^monitor/', include("app02.urls")),   
    ]
    • 1
    • 2
    • 3
    • 4

    app02/urls.py

    from django.conf.urls import url
    from app02 import views
    
    urlpatterns = [
        url(r'^login/', views.login),
    ]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    访问http://127.0.0.1/monitor/login,就访问的app02的login页面。

    5、默认值

    6、命名空间

    后续文章补充

  • 相关阅读:
    [ICPC2016上海F] Mr. Panda and Fantastic Beasts
    [ICPC2016上海E] Bet
    [ICPC2016上海D] Ice Cream Tower
    [ICPC2016上海L] World Cup
    [CCPC2020长春F] Strange Memory
    [CF1495C] Garden of the Sun
    【实战】牛年的第一个SQL注入漏洞
    【实战】一次有趣的HPP绕WAF记录
    [模板]二分答案
    字典树及其应用
  • 原文地址:https://www.cnblogs.com/ExMan/p/9338567.html
Copyright © 2011-2022 走看看