• Python学习笔记整理总结【Django】【MVC/MTV/路由分配系统(URL)/视图函数 (views)/表单交互】


     一、Web框架概述 

    Web框架本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 # _author_soloLi
     4 
     5 import socket
     6 
     7 def handle_request(client):
     8     buf = client.recv(1024)
     9     client.send("HTTP/1.1 200 OK
    
    ".encode("utf-8"))
    10     client.send("Hello, solo".encode("utf-8"))
    11 
    12 def main():
    13     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    14     sock.bind(('localhost', 8000))
    15     sock.listen(5)
    16     while True:
    17         connection, address = sock.accept()
    18         handle_request(connection)
    19         connection.close()
    20 
    21 if __name__ == '__main__':
    22     main()
    23 #执行上面程序,直接用浏览器访问http://127.0.0.1:8000/就能显示发送的信息: Hello, solo
    View Code

    开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。
    ①服务器程序:负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。
    ②应用程序:负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。
      不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器;WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的服务器程序和应用程序之间接口格式,实现服务器程序和应用程序间的解耦。

    wsgiref:python标准库提供的独立WSGI服务器

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 # _author_soloLi
     4 
     5 from wsgiref.simple_server import make_server
     6 
     7 def RunServer(environ, start_response):
     8     start_response('200 OK', [('Content-Type', 'text/html')])
     9     return ['Hello, solo'.encode("utf-8"),]
    10 
    11 if __name__ == '__main__':
    12     httpd = make_server('', 8000, RunServer)
    13     print("Serving HTTP on port 8000...")
    14     httpd.serve_forever()
    View Code

    <1>自定义Web框架 (通过python标准库提供的wsgiref模块)

    1.简单框架

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 # _author_soloLi
     4 from wsgiref.simple_server import make_server
     5 
     6 def handel_index():
     7     return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
     8 
     9 def handel_data():
    10     return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
    11 
    12 URL_DICT={
    13     '/index':handel_index,
    14     '/data':handel_data,
    15 }
    16 
    17 def RunServer(environ, start_response):
    18     start_response('200 OK', [('Content-Type', 'text/html')])    #start_response 封装返回给用户的数据
    19     current_url = environ['PATH_INFO']    #environ 客户发来的数据
    20     func = None
    21     if current_url in URL_DICT:
    22         func = URL_DICT[current_url]
    23     if func:
    24         return func()
    25     else:
    26         return ['<h1>Error 404</h1>'.encode("utf-8"), ]
    27 
    28 if __name__ == '__main__':
    29     httpd = make_server('', 8000, RunServer)
    30     print("Serving HTTP on port 8000...")
    31     httpd.serve_forever()
    View Code

    2.模板引擎

    在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。

     1 <!DOCTYPE html>
     2 <html>
     3 <head lang="en">
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <form>
     9         <input type="text" />
    10         <input type="text" />
    11         <input type="submit" />
    12     </form>
    13 </body>
    14 </html>
    data.html
     1 <!DOCTYPE html>
     2 <html>
     3 <head lang="en">
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8     <h1>Index</h1>
     9 </body>
    10 </html>
    index.html
     1 from wsgiref.simple_server import make_server
     2  
     3 def handel_index():
     4     f = open('index.html','rb')
     5     data = f.read()
     6     return [data,]
     7     # return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
     8  
     9 def handel_data():
    10     f = open('data.html','rb')
    11     data = f.read()
    12     return [data,]
    13     # return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
    14  
    15 URL_DICT={
    16     '/index':handel_index,
    17     '/data':handel_data,
    18 }
    19  
    20 def RunServer(environ, start_response):
    21     start_response('200 OK', [('Content-Type', 'text/html')])    #start_response 封装返回给用户的数据
    22     current_url = environ['PATH_INFO']    #environ 客户发来的数据
    23     func = None
    24     if current_url in URL_DICT:
    25         func = URL_DICT[current_url]
    26     if func:
    27         return func()
    28     else:
    29         return ['<h1>Error 404</h1>'.encode("utf-8"), ]
    30  
    31 if __name__ == '__main__':
    32     httpd = make_server('', 8000, RunServer)
    33     print("Serving HTTP on port 8000...")
    34     httpd.serve_forever()
    View Code

    3.返回动态页面数据
    对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?
      ①自定义一套特殊的语法,进行替换
      ②使用开源工具jinja2,遵循其指定语法

     1 from wsgiref.simple_server import make_server
     2  
     3 def handel_index():
     4     f = open('index.html','rb')
     5     data = f.read()
     6     data = data.replace(b'Index',"小祥祥吃骨头".encode("utf-8"))
     7     return [data,]
     8     # return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
     9  
    10 def handel_data():
    11     f = open('data.html','rb')
    12     data = f.read()
    13     return [data,]
    14     # return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
    15  
    16 URL_DICT={
    17     '/index':handel_index,
    18     '/data':handel_data,
    19 }
    20  
    21 def RunServer(environ, start_response):
    22     start_response('200 OK', [('Content-Type', 'text/html')])    #start_response 封装返回给用户的数据
    23     current_url = environ['PATH_INFO']    #environ 客户发来的数据
    24     func = None
    25     if current_url in URL_DICT:
    26         func = URL_DICT[current_url]
    27     if func:
    28         return func()
    29     else:
    30         return ['<h1>Error 404</h1>'.encode("utf-8"), ]
    31  
    32 if __name__ == '__main__':
    33     httpd = make_server('', 8000, RunServer)
    34     print("Serving HTTP on port 8000...")
    35     httpd.serve_forever()
    View Code

    <2>MVC/MTV

    MVC
            Model       View            Controller
            数据库     模板文件       业务处理
    MTV
           Model      Template           View
           数据库     模板文件        业务处理

    django采用的是MTV模式。

     二、Django概述 

    <0>Django生命周期

    Django大致工作流程:
      ① 客户端发送请求(get/post)经过web服务器、Django中间件、 到达路由分配系统
      ② 路由分配系统根据提取 request中携带的的url路径(path)与视图函数映射关系列表中,匹配到1个视图函数,foo(request)执行;
      ③ 视图函数 使用原生SQL或者ORM去数据库拿到数据,在服务端进行渲染(模板+数据渲染)
      ④ 视图函数return一个 response对象 返回客户端

    <1>Django基本配置

    Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

    0、Django安装(略,自己百度去。。。)

    1、创建Django工程

            django-admin startproject 工程名
            #django-admin startproject mysite  # 终端上直接输入,创建sitename项目名
            mysite目录结构:
                - mysite        # 对整个程序进行配置
                - init
                - settings  # 配置文件
                - urls      # URL对应关系
                - wsgi      # 遵循WSIG规范;Django里面没封装socket,当进行socket数据交互时要用到wsgi,一般用第三方模块uwsgi+nginx
                - manage.py     # 管理Django程序:
    View Code

    2、创建APP

            cd 工程名
            python manage.py startapp 应用名
            #python manage.py startapp cmdb
            # 目录结构
            - cmdb
                - migrations    #数据库操作记录(只是修改表结构的记录)
                - init       #表示python数据包(python3中有无均可)
                - admin      #Django为我们提供的后台管理
                - apps       #配置当前app
                - models      #创建数据库表结构,写指定的类,通过命令可以创建数据库结构
                - tests      #单元测试
                - views      #写业务逻辑代码,最重要的就是这个文件了
    View Code

    3、配置数据库(暂时默认不修改)

                DATABASES = {
                    'default': {
                    'ENGINE': 'django.db.backends.mysql',
                    'NAME':'dbname',
                    'USER': 'root',
                    'PASSWORD': 'xxx',
                    'HOST': '',
                    'PORT': '',
                    }
                }
            # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
            # 如下设置放置的与project同名的配置的 __init__.py文件中
            import pymysql
            pymysql.install_as_MySQLdb() 
    View Code

    4、配置静态文件

            #①创建static目录:放置css、js样式文件
            
            #②settings.py
            STATICFILES_DIRS = (
                os.path.join(BASE_DIR, 'static'),
            )
            
            #③templates目录下的xx.html(可以使用static目录里面的css、js样式)
            <link rel="stylesheet" href="/static/commons.css" />
    View Code

    5、配置模板路径

            #settings.py
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
    View Code

    6、注释 csrf(暂时)

            #settings.py
            MIDDLEWARE = [
                #'django.middleware.csrf.CsrfViewMiddleware',
            ]
    View Code

    7、定义路由规则(#url)

            #url.py        
            #"login" --> 函数名  (暂时记一种)
            urlpatterns = [
                        url(r'^login', views.login),
                    ]
    View Code

    8、定义视图函数(#view)

        #app下views.py            
                def func(request): # request  包含了用户提交的所有信息
                    # request.method   GET / POST
                    
                    # http://127.0.0.1:8009/home?nid=123&name=alex
                    # request.GET.get('',None)   # 获取请求发来的而数据
                    # request.POST.get('',None)
                
                    # return HttpResponse("字符串")
                    # return render(request, "HTML模板的路径")
                    # return redirect('/只能填URL')
    View Code

     三、路由分配系统(URL) 

    定义:project目录中的urls.py文件中, 以一个url()实例的列表urlpatterns,记录了可以访问到该站点的url 和 视图函数一一对应关系
    作用:当request请求到达路由系统,Django通过request中携带的path 遍历这个关系表,匹配到对应的视图函数,break;(所以1个 url 只能从路由关系表中自上而下匹配到1个视图函数)
    方式:①通过get请求携带参数的方式向server端传数据; https://i.cnblogs.com/%EF%BC%9Fid=1&name=solo
              ②通过path路径的方式向server端传值(以下主要介绍②);
    注意事项:按位置、按关键字,路由系统只能用1种,不能混合使用;

    1、单一路由对应
     ① url(r'^index/', views.index), url(r'^域名',对应的处理函数) 注意不要忘了写 ^ 表示正则匹配以。。开头的URL

        #编写URLconf的注意:
        #若要从url中捕获一个值,需要在它周围设置一对圆括号
        #不需要添加一个前导的反斜杠,如应该写作'test/',而不应该写作'/test/'
        #每个正则表达式前面的r表示字符串不转义
        #请求的url被看做是一个普通的python字符串,进行匹配时不包括get或post请求的参数及域名    
    View Code

    2、基于正则的路由(未分组)
     ② url(r'^detail-(d+).html/', views.detail),     #通过位置参数传递给视图

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {% for k,item in user_dict.items %}
        <li><a target="_blank" href="/detail-{{ k }}.html">{{ item.name}}</a></li>
    {% endfor %}
    
    </body>
    </html>
    index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h2>详细信息</h2>
        <h4>用户名:{{ detail_info.name }}</h4>
        <h4>邮箱:{{ detail_info.email }}</h4>
    </body>
    </html>
    detail.html
    from django.conf.urls import url,include
    from django.contrib import admin
    from cmdb import views
     
    urlpatterns = [
        url(r'^index', views.index),
        url(r'^detail-(d+).html/', views.detail),
    ]
    urls.py
    USER_DICT = {
        '1':{'name':'root1','email':'root@live.com'},
        '2':{'name':'root2','email':'root@live.com'},
        '3':{'name':'root3','email':'root@live.com'},
        '4':{'name':'root4','email':'root@live.com'},
    }
     
    def index(request):
        return render(request,"index.html",{"user_dict":USER_DICT})
     
    def detail(request,nid):  # nid指定的是(d+)里的内容
        detail_info = USER_DICT[nid]
        return render(request, "detail.html", {"detail_info": detail_info})
    views.py

    3、基于正则的路由(分组)
     ③ url(r'^detail-(d+)-(d+).html', views.detail),     #严格按照分组顺序传参数,一个出错,所有的都跟着出错
     ④ url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html/', views.detail)   #可以不按照顺序传参数
    #参数匹配规则:优先使用命名参数,如果没有命名参数则使用位置参数
    #每个捕获的参数都作为一个普通的python字符串传递给视图
    #性能:urlpatterns中的每个正则表达式在第一次访问它们时被编译,这使得系统相当快

    from django.conf.urls import url,include
    from django.contrib import admin
    from cmdb import views
     
    urlpatterns = [
        url(r'^index', views.index),
        url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html/', views.detail),<br>   # nid=d+ uid=d+
    ]
    urls.py
    def detail(request,**kwargs):
        print(kwargs)          
        #{'nid': '4', 'uid': '3'}
        nid = kwargs.get("nid")
        detail_info = USER_DICT[nid]
        return render(request, "detail.html", {"detail_info": detail_info})
    views.py
        2、url(r'^detail-(d+).html', views.detail),  
        3、url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail)
           
           PS:
                def detail(request, *args,**kwargs):
                    pass
        
           实战:
                a. 
                    #③ url(r'^detail-(d+)-(d+).html', views.detail),
                    
                    def func(request, nid, uid):
                        
                        pass
                
                    def func(request, *args):
                        args = (2,9)
                        
                        
                    def func(request, *args, **kwargs):
                        args = (2,9)
           
                b. 
                    #④ url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail)
                    
                    def func(request, nid, uid):
                        pass
                        
                    def funct(request, **kwargs):
                        kwargs = {'nid': 1, 'uid': 3}
                        
                    def func(request, *args, **kwargs):
                        args = (2,9)
    总结

    4、为路由映射设置名称
    对URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL *****
    设置名称之后,可以在不同的地方调用,如:
      --模板中使用生成URL {% url 'i2' 2012 %}
      --函数中使用生成URL reverse('i2', args=(2012,)) 路径:django.urls.reverse
      --Model中使用获取URL 自定义get_absolute_url() 方法

    class NewType(models.Model):
        caption = models.CharField(max_length=16)
    
        def get_absolute_url(self):
            """
            为每个对象生成一个URL
            应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
            :return:
            """
            # return '/%s/%s' % (self._meta.db_table, self.id)
            #
            from django.urls import reverse
            return reverse('NewType.Detail', kwargs={'nid': self.id})
    View Code
    <body>
    {#第一种方法i1       路径asdfasdfasdf/#}
    {#<form action="{% url "i1" %}" method="post">#}
    {#第二种方法i2       路径yug/1/2/#}
    {#<form action="{% url "i2" 1 2 %}" method="post">#}
    {#第三种方法i3       路径buy/1/9//#}
    <form action="{% url "i3" pid=1 nid=9 %}" method="post">
        <p><input  name="user" type="text" placeholder="用户名"/></p>
        <p><input  name="password" type="password" placeholder="密码"/></p>
        <p><input type="submit" value="提交"/></p>
    </form>
    </body>
    index.html
    from django.conf.urls import url,include
    from django.contrib import admin
    from cmdb import views
     
    urlpatterns = [
        url(r'^asdfasdfasdf/', views.index, name='i1'),     #第一种方式i1
        url(r'^yug/(d+)/(d+)/', views.index, name='i2'),  #第二种方式i2
        url(r'^buy/(?P<pid>d+)/(?P<nid>d+)/', views.index, name='i3'),    #第三种方式i3
    ]
    urls.py
    def index(request,*args,**kwargs):
        return render(request,"index.html")
    views.py
    对URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL *****
            
            #settings.py
            url(r'^asdfasdfasdf/', views.index, name='i1'),
            url(r'^yug/(d+)/(d+)/', views.index, name='i2'),
            url(r'^buy/(?P<pid>d+)/(?P<nid>d+)/', views.index, name='i3'),
            
            #views.py
            def func(request, *args, **kwargs):
                from django.urls import reverse
                
                url1 = reverse('i1')                              # url1=asdfasdfasdf/
                url2 = reverse('i2', args=(1,2,))                 # url2=yug/1/2/
                url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # url3=buy/1/9/
    
            #xxx.html            
                {% url "i1" %}               # -->  asdfasdfasdf/
                {% url "i2" 1 2 %}           # -->  yug/1/2/
                {% url "i3" pid=1 nid=9 %}   # -->  buy/1/9/
            
            注:
                # 当前的URL
                request.path_info 
    总结

    5、request.path_info:获取客户端当前的访问链接
         request.path:获取当前客户端的访问路径

    <form action="{{ request.path_info }}" method="post">
        <p><input  name="user" type="text" placeholder="用户名"/></p>
        <p><input  name="password" type="password" placeholder="密码"/></p>
        <p><input type="submit" value="提交"/></p>
    </form>
    index.html
    from django.conf.urls import url,include
    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        url(r'^index', views.index),
    ]
    urls.py
    def index(request):
        print(request.path_info)    #获取客户端当前的访问链接
        # / index
        return render(request,"index.html",{"user_dict":USER_DICT})
    views.py

    6、路由分发(多级路由)

    include()
    #使用include可以去除urlconf的冗余
    #匹配过程:先与主URLconf匹配,成功后再用剩余的部分与应用中的URLconf匹配


     

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
         url(r'^cmdb/', include("app01.urls")),    #调整到app01目录中的urls.py文件;注意include的是字符串形式的文件路径
         url(r'^monitor/', include("app02.urls")),
         url(r'^login', views.login),
    ]
    #主程序下urls.py文件
    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^login/', views.login),
    ]
    #app01下的urls.py文件
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    from django.shortcuts import redirect
    
    def login(request):
        # request  包含了用户提交的所有信息
        # print(request.method)
        error_msg=''
        if request.method == 'POST':
            user = request.POST.get('user',None)
            pwd = request.POST.get('pwd',None)
            if user == 'root' and pwd == '123':
                #去跳转
                return redirect('http://www.baidu.com')
            else:
                error_msg = 'SB! it is wrong'
        return render(request,'login.html',{'error_msg':error_msg})
    #app01下的views.py文件
    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    def login(requst):
        return HttpResponse('app02 login')
    #app02下的urls.py文件
    from django.conf.urls import url,include
    from django.contrib import admin
    from app02 import views
    urlpatterns = [
        url(r'^login/', views.login),
    ]
    #app02下的views.py文件
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/commons.css" />
        <style>
            label{
                 80px;
                text-align: right;
                display: inline-block;
            }
        </style>
    </head>
    <body>
        <form action="/login" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" name="user" type="text" />
            </p>
            <p>
                <label for="password">密码:</label>
                <input id="password" name="pwd" type="password" />
                <input type="submit" value="提交" />
                <span style="color: red;">{{ error_msg }}</span>
            </p>
        </form>
        <script src="/static/jquery.min.js"></script>
    </body>
    </html>
    #login.html

    7、默认值(添加额外的参数

    from django.conf.urls import url
    from django.contrib import admin
    from cmdb import  views
     
    urlpatterns = [
        url(r'^index/', views.index, {'name':'root'}),
    ]
    urls.py
    def index(request,name):
        print(name)
        return HttpResponse('OK')
     
    #root
    views.py

    8、命名空间
    在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
    配置url时为了解决url硬编码的问题,常常会使用命名空间来表示一个url。
    命名空间:是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。#在include中通过namespace定义命名空间,用于反解析
    #URL的反向解析
    如果在视图、模板中使用硬编码的链接(href="/polls/{{ poll.id }}/"),在urlconf发生改变时,维护是一件非常麻烦的事情
    解决:在做链接时,通过指向urlconf的名称,动态生成链接地址
    视图:使用django.core.urlresolvers.reverse()函数
    模板:使用url模板标签

    from django.conf.urls import url,include
     
    urlpatterns = [
        url(r'^a/', include('cmdb.urls', namespace='author-polls')),
        url(r'^b/', include('cmdb.urls', namespace='publisher-polls')),
    ]
    #主程序urls.py文件
    from django.conf.urls import url
    from cmdb import  views
     
    urlpatterns = [
        url(r'^index/', views.detail, name='detail'),
    ]
    #cmdb下的urls.py文件
    from django.shortcuts import HttpResponse
    from django.shortcuts import reverse
     
    def detail(request):
        url = reverse('author-polls:detail')
        print(url)
        return HttpResponse('OK')
    #views.py
    {% url 'author-polls:detail'  %}
    #html模板中生成url(/a/index/ )

    9、生成url路径(path_info+reverse)

    from.import models
    def article(request,*args,**kwargs):
         
        # 第一种方式利用path_info,访问的url
        print(request.path_info)
        # /article/0-0.html/
         
        # 第二种方式用reverse,自己生成   
        # 需要配合urls.py文件 url(r'...',views.article ,name='article')
        from django.urls import reverse
        url = reverse('article',kwargs=kwargs)
        print(url)
        # /article/0-0.html/
    View Code

    四、视图函数 
    定义:视图就是一个Python函数,被定义在views.py中。
    配置:定义完成视图后,需要配置urlconf(正则表达式+视图)
    作用:Django使用正则表达式匹配请求的URL,一旦匹配成功(只匹配路径部分,即除去域名、参数后的字符串),则调用相对应的视图。返回的响应可以是一张网页的HTML内容,一个重定向,一个404错误等等。

    404 (page not found)
    defaults.page_not_found(request, template_name='404.html')
    默认的404视图将传递一个变量给模板:request_path,它是导致错误的URL
    如果Django在检测URLconf中的每个正则表达式后没有找到匹配的内容也将调用404视图
    如果在settings中DEBUG设置为True,那么将永远不会调用404视图,而是显示URLconf 并带有一些调试信息 
    
    500 (server error)
    defaults.server_error(request, template_name='500.html')
    在视图代码中出现运行时错误
    默认的500视图不会传递变量给500.html模板
    如果在settings中DEBUG设置为True,那么将永远不会调用505视图,而是显示URLconf 并带有一些调试信息
    
    400 (bad request)
    defaults.bad_request(request, template_name='400.html')
    错误来自客户端的操作
    当用户进行的操作在安全方面可疑的时候,例如篡改会话cookie
    #常见视图(404/500/400)

    表单交互

    1、获取表单提交类型做相应处理

    #最终效果:当用户第一次访问时显示正常页面,输入用户名密码正确时调整到百度;错误时页面显示‘SB! it is wrong’

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6     <link rel="stylesheet" href="/static/commons.css" />
     7     <style>
     8         label{
     9             width: 80px;
    10             text-align: right;
    11             display: inline-block;
    12         }
    13     </style>
    14 </head>
    15 <body>
    16     <form action="/login" method="post">
    17         <p>
    18             <label for="username">用户名:</label>
    19             <input id="username" name="user" type="text" />
    20         </p>
    21         <p>
    22             <label for="password">密码:</label>
    23             <input id="password" name="pwd" type="password" />
    24             <input type="submit" value="提交" />
    25             <span style="color: red;">{{ error_msg }}</span>
    26         </p>
    27     </form>
    28     <script src="/static/jquery.min.js"></script>
    29 </body>
    30 </html>
    login.html
     1 from django.shortcuts import HttpResponse
     2 from django.shortcuts import render
     3 from django.shortcuts import redirect
     4  
     5 def login(request):
     6     # request  包含了用户提交的所有信息
     7     # print(request.method)
     8  
     9     error_msg=''
    10     if request.method == 'POST':
    11         user = request.POST.get('user',None)
    12         pwd = request.POST.get('pwd',None)
    13         if user == 'root' and pwd == '123':
    14             #去跳转
    15             return redirect('http://www.baidu.com')
    16         else:
    17             error_msg = 'SB! it is wrong'
    18  
    19     return render(request,'login.html',{'error_msg':error_msg})
    Views.py
            --commons.css
            --jquery_min.js
    static目录

    2、模拟数据库交互,循环列表渲染页面

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body style="margin: 0">
     8     <div style="height: 48px;background-color: #dddddd"></div>
     9     <div>
    10         <form action="/home" method="post">
    11             <input type="text" name="username" placeholder="用户名" />
    12             <input type="text" name="email"  placeholder="邮箱"/>
    13             <input type="text" name="gender"  placeholder="性别"/>
    14             <input type="submit" value="添加" />
    15         </form>
    16     </div>
    17     <div>
    18         <table>
    19             {% for row in user_list %}
    20                 <tr>
    21                     <td>{{ row.username }}</td>
    22                     <td>{{ row.gender }}</td>
    23                     <td>{{ row.email }}</td>
    24                 </tr>
    25             {% endfor %}
    26 
    27         </table>
    28     </div>
    29 
    30 
    31 </body>
    32 </html>
    home.html
     1 from django.conf.urls import url
     2 from django.contrib import admin
     3 from cmdb import views
     4 
     5 
     6 urlpatterns = [
     7     url(r'^admin/', admin.site.urls),
     8    # url(r'^login', views.login),
     9     url(r'^home', views.home),
    10 ]
    urls.py
     1 from django.shortcuts import HttpResponse
     2 from django.shortcuts import render
     3 from django.shortcuts import redirect
     4  
     5 USER_LIST = [
     6     {'id': 1, 'username': 'alex', 'email': '1109913149@qq.com', "gender": 'male'},
     7     {'id': 2, 'username': 'solo', 'email': '1109913149@qq.com', "gender": 'male'},
     8     {"id": 3,'username': 'seven', 'email': '1109913149@qq.com', "gender": 'male'},
     9 ]
    10  
    11 def home(request):
    12     if request.method == "POST":
    13         # 获取用户提交的数据 POST请求中
    14         u = request.POST.get('username')
    15         e = request.POST.get('email')
    16         g = request.POST.get('gender')
    17         temp = {'username': u, 'email': e, "gender": g}
    18         USER_LIST.append(temp)
    19     return render(request, 'home.html', {'user_list':  USER_LIST})
    Views.py

    3、表单交互,获取checkbox多个值

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     <form action="/login" method="POST" >
     9         <p>
    10             男:<input type="checkbox"  name="favor" value="11"/>
    11             女:<input type="checkbox" name="favor" value="22"/>
    12             戴利祥:<input type="checkbox" name="favor" value="33"/>
    13         </p>
    14         <input type="submit" value="提交"/>
    15     </form>
    16 </body>
    17 </html>
    login.html
     1 from django.conf.urls import url
     2 from django.contrib import admin
     3 from cmdb import views
     4 
     5 
     6 urlpatterns = [
     7     url(r'^admin/', admin.site.urls),
     8     url(r'^login', views.login),
     9    # url(r'^home', views.home),
    10 ]
    urls.py
     1 def login(request):
     2     #checkbox  多选框
     3     if request.method == "POST":
     4         favor_list = request.POST.getlist("favor")      #getlist获取多个值
     5         print(favor_list)           #多选框获取到的是列表格式
     6         #['11', '22', '33']
     7         return render(request,"login.html")
     8     elif request.method == "GET":
     9         return render(request,"login.html")
    10     else:
    11         print("other")
    views.py

    注:select多选时跟上面程序一样都用getlist进行获取

    4、表单交互,上传文件file

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     <form action="/login" method="POST" enctype="multipart/form-data">
     9         <p>
    10             <input type="file" name="files"/>
    11         </p>
    12         <input type="submit" value="提交"/>
    13     </form>
    14 </body>
    15 </html>
    login.html
     1 def login(request):
     2     #file 上传文件
     3     if request.method == "POST":
     4         obj = request.FILES.get('files')       #用files获取文件对象
     5         if obj:
     6             print(obj, type(obj), obj.name)
     7             # test.jpg <class 'django.core.files.uploadedfile.InMemoryUploadedFile'> test.jpg
     8             import os
     9             file_path = os.path.join('upload', obj.name)
    10             f = open(file_path, "wb")
    11             for item in obj.chunks():      #chunks表示所有的数据块,是个迭代器
    12                 f.write(item)
    13             f.close()
    14         return render(request,"login.html")
    15     elif request.method == "GET":
    16         return render(request,"login.html")
    17     else:
    18         print("other")
    views.py
  • 相关阅读:
    C#综合揭秘——细说事务
    软件项目管理流程总结
    WCF揭秘——自定义绑定
    WCF揭秘——共享数据契约
    反流程升职记
    .NET基础篇——利用泛型与反射更新实体(ADO.NET Entity Framework)
    先睹为快:Visual Studio 11测试版已于2.29在微软官方网站正式发布
    .NET基础篇——分部类和分部方法
    C#综合揭秘——深入分析委托与事件
    .NET基础篇——反射的奥妙
  • 原文地址:https://www.cnblogs.com/liwei1153300111/p/8117724.html
Copyright © 2020-2023  润新知