zoukankan      html  css  js  c++  java
  • 人生苦短,我用python-- Day19 django框架之URL路由系统、视图应用、模板应用、django之orm应用

    目录                    

    一、django的URL应用

    二、django的视图应用

    三、django的模板应用

    四、django的orm应用

      补充:

    补充一:getlis

      应用场景:当前端发送的数据为多个的时候,后台如果还用get获取数据,那么就会出问题,所以这里有一个getlist方法进行数据的获取。

      试验案例:当前端有一个多选的checkbox的时候,那么就要使用getlist进行获取数据了

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^getlist', views.getlist),
    ]
    urls.py
    def getlist(request):
        if request.method == 'GET':
            return render(request,'getlist.html')
        else:
            checkbox = request.POST.getlist('interest')
            print(checkbox)
            return HttpResponse(checkbox)
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/getlist" method="post">
        <div>
            兴趣爱好调查问卷
        </div>
        <span></span>
        <input type="checkbox" name="interest" value="1">
        <span></span>
        <input type="checkbox" name="interest" value="2">
        <span>无要求</span>
        <input type="checkbox" name="interest" value="3">
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    html代码

    查看结果:

    同样select标签的使用方法也是一样的

    补充二:上传文件

      学过了从前台获取数据(单个的数据、多个的数据),那如何从前台获取一个文件呢?这里要说一下获取文件就不能用request.POST进行get了,

    需要使用request.FILES进行数据获取了。

    写一个上传文件的案例:

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^upload/', views.upload),
    ]
    urls.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#  enctype="multipart/form-data"如果提交的数据是文件的话,那么就得在form表单里面写上这句话  #}
        <form action="/upload/" method="POST" enctype="multipart/form-data"> 
            <p>
                <input type="file" name="file"/>
            </p>
    
            <input type="submit" value="提交"/>
        </form>
    </body>
    </html>
    html代码
    from django.shortcuts import render,HttpResponse
    from django.views import View
    # Create your views here.
    
    def upload(request):
        if request.method == 'GET':
            return render(request,'upload.html')
        elif request.method == 'POST':
            # 获取到前台传过来的文件,如果直接print obj的话,会打印上传文件的文件名;
            # 其实他接收到的并不是一个文件名,可以打印一些obj的类型,结果是一个类的对象
            obj = request.FILES.get('file')
            import os
            # 在obj.name前面加上一个upload目录 最后目录路径是 upload/上传的文件名字
            # 这里的obj.name就是调用name属性,属性值为上传的文件名字
            file_pat = os.path.join('upload',obj.name)
            f = open(file_pat,'wb')
            print(os.path)
            # 循环获取上传的数据
            for i in obj.chunks():
                f.write(i)
            f.close()
            return render(request,'upload.html')
        else:
            return render(request,'upload.html')
    Views.py主逻辑

     django的URL应用                           

    知识点一:前台模板渲染后台传的单层字典

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#循环字典里面的key#}
        <ul>
            {% for row in user_dict.keys  %}
                <li> {{ row }} </li>
            {% endfor %}
        </ul>
    {#循环字典里面的value#}
        <ul>
            {% for val in user_dict.values  %}
                <li> {{ val }} </li>
            {% endfor %}
        </ul>
    {#循环字典中的key-val#}
        <ul>
            {% for key,val in user_dict.items  %}
                <li> {{ key }}--{{ val }} </li>
            {% endfor %}
        </ul>
    </body>
    </html>
    html
    from django.shortcuts import render
    USER_DICT = {
        'k1':'root1',
        'k2':'root2',
        'k3':'root3',
        'k4':'root4',
    }
    # 传递单层的字典
    def index(request):
        return render(request,'index.html',{'user_dict':USER_DICT})
    Views

    可以看到,

    • 如果只循环字典的key那么格式就是user_dict.keys
    • 如果只循环字典的value那么个事就是user_dict.values;
    • 如果想循环整个字典那么格式就是user_dict.items;

    注意:我们在写python的时候,循环字典需要加括号“()”,但是在这里是不能加的,加了就报错了

    知识点二:url正则匹配,一对多

    from django.conf.urls import url
    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        url(r'^index/', views.index),
        url(r'^detail-(d+).html', views.detail),
    ]
    urls.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <ul>
     {#后台传过来的是一个字典,字典名字叫做user_dict,我们循环user_dict的items,为每列都加一个a标签,连接指向这个用户的key,列表内容为字典的value#}
        {% for key,val in user_dict.items %}
            <a name="_blank" href="/detail-{{ key }}.html"><li>{{ val }}</li></a>
        {% endfor %}
    </ul>
    </body>
    </html>
    index.html
    from django.shortcuts import render,HttpResponse
    from django.views import View
    # Create your views here.
    
    
    # 定义用户字典
    USER_DICT = {
        '1':'root1',
        '2':'root2',
        '3':'root3',
        '4':'root4',
    }
    
    # 当用户访问index的时候,返回index.html文件,并把用户字典返回到前端进行渲染,关键字为user_dict
    def index(request):
        return render(request,'index.html',{'user_dict':USER_DICT})
    views.py

    然后点击跳转用户详情页就可以了

     知识点三:urls 传参数到views的方法    

      对应位置进行传参数

    from django.conf.urls import url
    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        # 主页的路由匹配
        url(r'^index/', views.index),
        # 详情页的路由匹配,这(d+)使用的是正则匹配,如果这里有多个括号,那么和views.detail方法接收参数的形参是一一对应的,如果这里有两个括号,那么方法里也应该有两个接收参数的形参,不然就报错了!   
        url(r'^detail-(d+).html', views.detail),
    ]
    urls.py
    from django.shortcuts import render,HttpResponse
    from django.views import View
    # Create your views here.
    # 定义用户的信息
    USER_DICT = {
        '1':{'name':'root1','email':'alex0417@161.com'},
        '2':{'name':'root2','email':'alex0417@162.com'},
        '3':{'name':'root3','email':'alex0417@163.com'},
        '4':{'name':'root4','email':'alex0417@164.com'},
        '5':{'name':'root5','email':'alex0417@165.com'}
    }
    # 首页的方法,把上面定义的字典传过去
    def index(request):
        return render(request,'index.html',{'user_dict':USER_DICT})
    
    # 详情页的方法,这里的nid形参是和urls里面对应的,哪里有几个参数这里就需要有几个,不然就报错了。然后动态获取到nid参数后,找到对应的用户信息,发送到前台进行进行渲染就可以了
    def detail(request,nid):
        detail_info = USER_DICT[nid]
        return render(request,'detail.html',{'user_info':detail_info})
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#接收后天传来的字典套字典的数据,进行渲染,循环使用items#}
    <ul>
        {% for key,val in user_dict.items %}
            <a name="_blank" href="/detail-{{ key }}.html"><li>{{ val.name }}</li></a>
        {% endfor %}
    </ul>
    </body>
    </html>
    index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>详细信息</h1>
            <h6>用户名:{{ user_info.name }}</h6>
            <h6>邮箱:{{ user_info.email }}</h6>
    </body>
    </html>
    detail.html

      使用参数名的方式进行传参数

    urls.py也可以这么写,并且如果有多个参数,不影响参数赋值

    from django.conf.urls import url
    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        url(r'^index/', views.index),
    # 再传参数的时候就把第一个参数命名赋值给了nid,把第二个参数赋值给了uid,那么这样在views中后去参数就没有先后顺序了,这样感觉会更好
        url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail2),
    ]

      使用参数名的方式进行传参数,优化:

    # 不管是用参数名进行传递参数的时候,还是使用位置参数传递参数的时候,urls传递了几个参数这里就得有几个接受参数的形参
    def detail(request,nid):
        detail_info = USER_DICT[nid]
        return render(request,'detail.html',{'user_info':detail_info})
    
    # 为了避免忘了接受参数,导致程序报错的情况,那么我们有了如下方案
    def detail2(request,*args,**kwargs):
        detail_info = USER_DICT[kwargs.get('nid')]
        return render(request,'detail.html',{'user_info':detail_info})

    django的视图应用                    

    FBV (funaction base view) ---->  我们之前学的url路由关系都是一个请求过来由url进行匹配,看匹配到那个方法直接去views.py代码体里面进行相应发方法查找,然后进行逻辑处理。 

    CBV (Class base view) -----> 现在说一个cbv的模式,模式是这样,当请求过来后,也是由url进行匹配,这次匹配到的不是一个方法,而是一个类。

    那么CBV是怎么工作的呢? 看代码:

    urlpatterns = [
        url(r'^admin/', admin.site.urls),   #FBV
        url(r'^home/', views.Home.as_view()),  #CBV
    ]
    urls.py
    from django.shortcuts import render,HttpResponse
    from django.views import View   #引入一个django里面View模块
    # 定义这类
    class Home(View):
        # 这里是利用类的映射进行操作的,可以看一下父类View里面有一个dispatch方法。当使用get请求的时候
        # 就会执行下面的get方法。。。
    
        def get(self,request):
            print(request.method)
            return render(request,'home.html')
        def post(self,request):
            print(request.method)
            return render(request,'home.html')
    Views.py

    django一共给我们提供了这么多的请求方式,我们来梳理一下过程:

    也就是说,在执行我们定义的方法之前肯定会先执行父类里面的dispatch方法,那么既然这样,我们就可以搞点事情了。想想“装饰器”,看代码:

    class Home(View):
        def dispatch(self,request,*args,**kwargs):
            print('befor')
            result = super(Home,self).dispatch(request,*args,**kwargs)
            print('after')
            return result
        # 这里是利用类的映射进行操作的,可以看一下父类View里面有一个dispatch方法。当使用get请求的时候
        # 就会执行下面的get方法。。。
    
        def get(self,request):
            print(request.method)
            return render(request,'home.html')
        def post(self,request):
            print(request.method)
            return render(request,'home.html')
    views.py

    这里打印的befor和after是不是就类似于我们我们之前学的装饰器呢?

    我们再来梳理一下现在的流程:

    第一步:浏览器通过任何方式的请求把数据包发送到服务器的urls路由系统中

    第二步:urls路由系统进行匹配请求的url,发现匹配到一个class,把请求转给对应的class

    第三步:对应的class在自己内部找到dispatch方法,首先执行自己增加的代码块

    第四步:从集成的父亲那里获取该请求是什么方式的请求

    第五步:父类告诉子类请求的方式是什么

    第六步:子类查找自己内部对应的请求方方式的function并执行代码块,并把数据返回给浏览器

    1

  • 相关阅读:
    编译 netcat for lineage-17.1-20210303-UNOFFICIAL-dipper.zip (ARM)
    Mi8-Android-arm 中网络接口命名:wlan0 & rmnet_data 《========》 VB-Android-x86 中网络接口命名:eth1 & wifi_eth
    HOW TO CHANGE LINUX KERNEL DMESG BUFFER SIZE
    Calculation of RTO in tcp and related open source implementation (Linux kernel, unbound) --- rtt, rttvar, cwnd, ssthresh
    图解Linux网络包接收过程
    Tcpprobe 在网络中的使用 --- tcp_probe has been removed from the kernel. --- Using ip-tcp_metrics --- Using ss (socket statistics)
    全面的 iPerf3 Android平台移植编译、运行过程记录
    socket、sock、sk_buff、net_device 关系图
    tcp: Add TCP_FREEZE socket option
    ECNU 2031 绝对值排序
  • 原文地址:https://www.cnblogs.com/xinzhiyu/p/6159944.html
Copyright © 2011-2022 走看看