Django笔记总结(二) -- 路由规则、用户请求、视图函数

一、用户请求生命周期

  用户从浏览器点击我们的网站发出请求开始,这个请求就有一个生命周期,请求经历的生命周期如下所示:

  用户请求 —> 中间件 —> 路由匹配 —> 视图函数 —> 数据操作 —> 模板渲染 —> 中间件 —> 响应结果

  有关中间件的内容将放在后续的博客中介绍

二、用户请求

  用户发送的请求常见的有两种:GET、POST。

       1、GET请求

  当用户在浏览器的地址栏中输入一个网址时,这时用户就发送了一个GET请求,GET请求是将用户数据封装在HTTP请求头中传给后台的,数据会暴露在浏览器的地址栏中,因此一定意义上GET请求是不安全的请求,如下所示就是一个GET请求:

  https://i.cnblogs.com/EditArticles.aspx?opt=1

  在GET请求中,使用“?”来分隔URL和参数,而多个参数之间以“&”符号分隔,上述请求中的opt就是一个参数,该参数的值是1

  在html代码中,form表单默认采用GET的方式提交数据,可以通过method="post"来设置为使用POST方式提交。

       2、POST

  POST请求相对GET请求来要更安全一些,因为POST请求不会封装在http请求头中,而是封装在HTTP请求的数据体中发送给后端服务器,所以在发送POST请求时,在地址栏上是看不到发送的数据的内容的,所以这种方式也相对安全

三、路由匹配

  从用户请求的生命周期可以看到,当用户发送请求到达Django服务器时,服务器会根据用户请求的URL来判断调用哪个函数来处理用户请求,这个判断的规则就是路由匹配规则,这个判断的过程就是路由匹配。

  在工程同名目录下我们可以看到有一个urls.py的文件,这个文件就是全局的路由匹配规则的配置文件。

       1、一级URL匹配

  我们在工程同名目录下的urls.py文件中定义一条路由匹配规则如下:

from django.conf.urls import url
from django.contrib import admin
#导入HttpResponse用来给用户返回一个字符串
from django.shortcuts import HttpResponse

#定义一个函数,当路由匹配成功后会调用该函数来处理用户请求
def test():
    return HttpResponse("OK")

urlpatterns = [
    url(r'^admin/', admin.site.urls),
#添加一条路由匹配规则
    url(r'^test/',test),
] 

      从上述代码中我们可以看到,我们在这个文件中定义了一个函数test(),这个函数会给用户返回一个字符串“OK”,同时,我们在urlpatterns这个配置项中添加了一条路由匹配规则 "url(r'^test/',test)," 这条规则的意思是当用户访问/test/这个URL时,就调用test函数来处理用户请求,我们访问以下地址:

  我们可以看到,服务器成功返回了字符串"OK"。

  我们刚才直接在全局路由规则文件中写入了一条路由规则,这条规则直接找到了用来处理用户请求的函数,这样的路由规则就是一个一级路由匹配。

  2、二级路由匹配

  我们可以看到,一个网站由很多功能块组成,其中的URL也是五花八门,数量也是很多,如果这些URL对应的路由匹配规则全部写在一个文件中,那无疑会导致这个文件很繁杂,不利于维护,而且如果一个app的URL发生了改变,所有的路由规则都需要重新做一次修改,很显然这是十分不利的,所以,我们可以使用二级路由匹配来吧不同app的路由条目分开管理。

  比如我们新建一个app,名字叫admin:

  我们可以看到,新建的app目录下并没有urls.py这个文件,所以我们需要自己创建这个文件:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from django.conf.urls import url
#导入app中的views模块
from admin import views

urlpatterns = [
#当URL中包含index时,调用views文件中的index函数处理
    url(r'^index/',views.index),
]

      从上述代码中我们可以看到,当我们访问index/这个URL时,将会调用views中的index函数来处理,但是用户请求如何能找到我们app的路由规则呢?这时就需要在全局的路由匹配文件中定义包含进app的路由规则文件了,所以,在工程同名目录的urls.py文件中添加如下内容:

#导入include模块
from django.conf.urls import url,include

urlpatterns = [
#当用户访问/admin/这个URL时,使用admin中的urls文件来进行路由匹配
    url(r'^admin/',include('admin.urls'))
]

  上述配置意味着,当用户访问的URL中以admin/开头的请求都会使用admin.urls这个文件来做路由匹配,也就是说,用户在访问/admin/index/这个URL时,会调用index函数处理:

  在上述路由匹配过程中,首先在全局路由配置中匹配到了admin,然后又在app的路由匹配中匹配到了index,共进行了两次匹配,所以这种路由匹配称之为二级路由匹配,其中需要使用include将第二级的urls文件包含金全局的路由配置文件中。

  3、单一路由匹配

  从上述例子中可以看到,我们进行路由匹配时,一条路由规则只能匹配到一个URL,这样子的匹配就是单一路由匹配,很明显,这种方式具有较大的局限性。

      4、基于正则的路由匹配

  我们可以在路由匹配时加入正则表达式,正则表达式匹配URL成功后就认为路由匹配成立:

正则表达式 匹配结果
. 匹配单个字符
\d 匹配数字
\w 匹配除数字,字母组成的字符串
[a-z] 匹配小写字母
[A-Z] 匹配大写字母
[A-Za-z] 匹配所有字母
+ 匹配该字符前的字符一次或多次
? 匹配该字符前的字符零次或一次
* 匹配该字符前的字符零次或多次
[^/] 匹配非“/”的字符串
{1,4} 匹配1个或2个或3个或4个前一个字符

  例如,我们在全局url配置中改为如下配置:

  url(r'^admin\w+/',include('admin.urls')),

  这样,我们在访问URL中,访问类似如下的URL都是可以访问到的:

  http://127.0.0.1:8001/adminadqerq423rt32f/index/

  http://127.0.0.1:8001/adminaeadfrq9ad82/index/

      5、带参数的路由匹配

  如果我们在写路由匹配规则的时候,加入分组,那么分组的数据会作为参数传递给后端的函数,例如给上述:

  url(r'^index/(\d{4})/(\d{1,2})/',views.index),

  这样一条路由匹配规则,当用户访问/admin/index/2017/02/这个URL时,2017和02就会作为参数传递给后端的函数,此时后端函数需要接收一下这两个参数,否则就会报错,例如views中index函数如下:

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request,*args,**kwargs):
    return HttpResponse("This is index page! %s-%s" %(args[0],args[1]))

  当我们访问上述URL时,我们得到的结果就如下结果:

  This is index page! 2017-02

  除了上述的传递参数的方法外,我们还可以通过给参数命名的方式来给后端函数传参数,例如上述路由匹配规则改为如下形式:

  url(r'^index/(?P<year>\d{4})/(?P<month>\d{1,2})/',views.index),

  其中(?P<name>pattern)这部分中的name就是该参数的参数名,views中的index函数应该改成如下:

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request,**kwargs):
    return HttpResponse("This is index page! %s-%s" %(kwargs['year'],kwargs['month']))

      6、命名路由匹配

  当我们需要在HTML中提交表单时,表单内容需要提交到一个URL中去,无疑,这个URL在找对应的函数时也需要通过路由匹配,那么如果我们此时把这个路由匹配给改变了,那么我们在html中就需要手动改变表单提交的URL,如果页面中这样的URL有很多……,显然,这种方式是不方便的,所以,Django中提供了一个命名路由匹配的功能,就是给我们的路由条目起个名字,前端页面上直接使用这个名字来动态的生成URL,这样一来,上面提到的问题就迎刃而解了。具体方法如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from django.conf.urls import url
from admin import views

urlpatterns = [
    url(r'^index/',views.index,name="test1"),
    # url(r'^index/(\d{4})/(\d{1,2})/',views.index),
]

  在urls文件中,我们给路由条目添加一个name属性,这就是给该路由条目命名的名字,接下来,我们在html文件中可以通过模板语言来使用,关于模板语言的详细介绍将放在后面的博客中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'test1' %}" method="post">
    <input type="submit" value="提交">
</form>
</body>
</html>

  对应的我们的views函数也需要做相应的更改。

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):
    if request.method == "POST":
        return HttpResponse("This is index page!")
    elif request.method == "GET":
        return render(request,"test.html")

  我们访问一下/admin/index/这个URL可以看到得到了刚才html文件中的页面,查看该页面中form表单的URL可以看到,其URL就是我们命名的那个URL。
  当我们的路由匹配条目需要传递参数时,我们依然可以使用路由命名,只需要在html中跟上具体的参数即可,如果路由条目中的参数有名称,那么html中需要指定参数的名称:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'test1' 2345 23 %}" method="post">
    <input type="submit" value="提交">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'test1' year=2017 month=03 %}" method="post">
    <input type="submit" value="提交">
</form>
</body>
</html>

      7、命名空间

四、视图函数

       1、CBV与FBV

  在views函数中,不仅可以使用函数的形式来定义,还可以使用面向对象的方式,面向对象的方式被称为CBV(Class Base Views),采用函数定义的被称为FBV(Function Base Views),使用函数的形式定义的此处不再赘述。

  CBV定义的方式中,上述views中的函数可以如下定义:

from django.shortcuts import render,HttpResponse
from django.views import View

# Create your views here.

class index(View):
    def get(self,request):
        return render(request, "test.html")

    def post(self,request):
        return HttpResponse("This is index page!")

  在路由匹配规则中,引用CBV的方法如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from django.conf.urls import url
from admin import views

urlpatterns = [
    url(r'^index/',views.index.as_view(),name="test1"),
]

       2、HttpResponse、redirect、render

  HttpResponse:返回一个字符串,用法:return HttpResponse("返回的字符串")

  redirect:重定向到一个新的URL,用法:return redirect('重定向的URL')

  render:将html模板渲染后返回给前端,用法:return render(request,'模板html文件',{'参数名':参数值,......})

 

posted @ 2017-02-20 15:53  没有手艺的手艺人  阅读(308)  评论(0编辑  收藏  举报