欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Django的视图函数

程序员文章站 2022-04-09 18:54:45
一.Django的视图函数view 一个视图函数(类),简称视图,是一个简单的Python函数(类),它接受WEB请求并返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. 无论视图本身包含什么逻辑,都要返回响应.代码写在哪里也无所谓,只要它 ......

一.django的视图函数view

  一个视图函数(类),简称视图,是一个简单的python函数(类),它接受web请求并返回web响应.

  响应可以是一张网页的html内容,一个重定向,一个404错误,一个xml文档,或者一张图片.

  无论视图本身包含什么逻辑,都要返回响应.代码写在哪里也无所谓,只要它在你当前项目目录下面.除此之外没有更多要求了---可以说"没有什么神奇的地方".为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中.

  一个简单的视图

  下面是一个以html文档的形式返回当前日期和时间的视图:

from django.http import httpresponse
import datetime

def current_datetime(request):
    now = datetime.datetime(request):
    html = "<html><body>it is now %s.</body></html>" % now
    return httpresponse(html)

  代码的逐行解释:

1)首先从django.http模块导入hyypresponse类,以及python的datetime库

2)接着定义了current_datetime函数.它就是视图函数.每个视图函数都使用httpresponse对象作为第一个参数,并且通常称为request.

 注意:视图函数的名称不重要;不需要用一个统一的命名方式来命名,以便让django识别它我们将其命名为current_datetime,因为这个名称能够比较准确地反映出它实现的功能.

3)这个视图会返回一个httpresponse对象,其中包含生成的响应.每个视图函数都负责返回一个httpresponse对象

 django使用请求和响应对象来通过系统传递状态.

 当浏览器向服务端请求一个页面时,django创建一个httpresponse对象,该对象包含关于请求的元数据.然后,django加载相应的视图,将这个httpresponse对象作为第一个参数传递给视图函数.

 每个视图负责返回一个httpresponse对象.

Django的视图函数

  views.py(视图层),熟练掌握两个对象:请求对象(request)和响应对象(httpresponse)

 

二.cbv和fbv

  fbv(function base views)  就是在视图中使用函数处理请求

  cbv(class base views)  就是在视图里使用类处理请求

  python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承,封装,多态).所以django在后来加入了class-based-view.可以让我们用类写view.

  优点:

  1.提高代码的复用性,可以使用面向对象的技术,比如mixin(多继承)

  2.可以用不同的函数针对不同的http方法处理,而不是通过很对if判断,提高代码的可读性

    如果我们要写一个处理get方法的view,用函数写的话是下面这样

from django.http import httpresponse
  
def my_view(request):
     if request.method == 'get':
            return httpresponse('ok')

  如果用class-based-view写的话,就是下面:

from django.http import httpresponse
from  django.views import view

class myview(view):
    def get(self,request):
        return httprsponse('ok')

  django的url 是将一个请求分配给可调用函数的,而不是一个class.针对这个问题,class-based view提供了一个as_view()静态方法(也就是类方法),调用这个类方法,会创建一个类的实例,然后通过这个实例调用dispatch()方法,dispath()方法会根据request的method的不同调用相应的方法来处理request(如get(),或者post()),到这里,这些方法和function-based-view差不多了,要接收request,得到了一个response返回.返回方法没有定义,会抛出httpresponsenotallowed异常。

  注意:使用cbv时,urls.py中也做对应的修改:

# urls.py
from django.conf.urls import url
from myapp.views import myview #引入我们在views.py里面创建的类
  
urlpatterns = [
     url(r'^index/$', myview.as_view()),
]

  cbv传参,和fbv类似,有名分组,无名分组

   url写法:无名分组的

url(r'^cv/(\d{2})/', views.myd.as_view(),name='cv'),
 url(r'^cv/(?p<n>\d{2})/', views.myd.as_view(name='xxx'),name='cv'),
#如果想给类的name属性赋值,前提你的myd类里面必须有name属性(类属性,
定义init方法来接受属性行不通,但是可以自行研究一下,看看如何行通,意义不大),
并且之前类里面的name属性的值会被覆盖掉

  类写法:

class myd(view):
    name = 'sb'

    def get(self,request,n):
        print('get方法执行了')
        print('>>>',n)
        return render(request,'cvpost.html',{'name':self.name})

    def post(self,request,n):
        print('post方法被执行了')
        return httpresponse('post')

 四.给视图加装饰器

  使用装饰器装饰fbv

  fbv本身就是一个函数,就是python通用装饰器的加法.

def wrapper(func):
    def inner(*args,**kwargs):
        start_time = time.time()
        ret = func(*args,**kwargs)
        end_time = time.time()
        print("used:",end_time - start_time)
        return ret
    return inner

#fbv版本添加班级
@wrapper
def add_class(request):
    if request.method == "post":
        class_name = request.post.get("calss_name")
        models.classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request,"add_class.heml")

  使用装饰器装饰cbv

  类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。

  django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

from django.views import view
from django.utils.decorators import method_decorator

class addclass(view):

    @method_decorator(wrapper)
    def get(self, request):
        return render(request, "add_class.html")

    def post(self, request):
        class_name = request.post.get("class_name")
        models.classes.objects.create(name=class_name)
        return redirect("/class_list/")

 五.request对象

  当一个页面被请求时,django就会创建一个包含本次请求原信息(请求报文中的请求行、首部信息、内容主体等)的httprequest对象。

  django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成的使用request参数承接这个对象.

  django会将这个对象自动传递给相应的视图函数,一般视图函数约定俗成的使用request参数承接这个对象.

  请求相关的常用值

1)path_info   返回用户访问url,不包括域名

2)method      请求中使用的http方法的字符串表示,全大写表示.

3)get              包含所有http get参数的类字典对象

4)post             包含所有http post参数类字典对象

5)body     请求体,byte类型 request.post的数据就是从body里面提取到的

   要处理表单数据的时候,推荐还是使用httprequest.post.

  另外,我们还可以用python的类文件方法去操作它.

 2.httprequest.path

  一个字符串,表示请求的路径组件(不含域名)。
  例如:"/music/bands/the_beatles/"
3.httprequest.method
  一个字符串,表示请求使用的http 方法。必须使用大写。
  例如:"get"、"post"

 六.响应  response

  响应对象有三种形式:

  (1) httpresponse()

  (2) render()

  (3)redirect()

  httpresponse()括号内直接跟一个具体的字符串作为响应体,比较直接很简单.

  django shortcut function

    render()

    Django的视图函数

    结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的httpresponse对象.

      参数:

        request: 用于生成相应的请求对象.

        template_name: 要使用的模板的完整名称,可选参数

        context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它

   例子:

from django.shortcuts import render

def my_view(request):
    # 视图的代码写在这里
    return render(request, 'myapp/index.html', {'foo': 'bar'})

    redirect():给浏览器了一个30x的状态码

    参数是:

      1/ 一个模型,将调用模型的get_absolute_url() 函数

      2/ 一个视图,可以带有参数:将使用urlresolvers.revese来反向解析名称

      3/一个绝对的或相对的url,将原封不动的作为重定向的位置

    默认返回一个临时的重定向;传递permanent=true可以返回一个永久的重定向.

    示例:

    可以用多种方法使用redirect()函数.

    传递一个视图的名称

def my_view(request):
    ...
    return redirect('some-view-name', foo='bar')

    传递要重定向到的一个具体的网址

def my_view(request):
    ...
    return redirect('/some/url/')

    看一个例子

        index.html文件,内容如下

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>title</title>
</head>
<body>
<div>这是index页面</div>
<h1>{{ name }}</h1>

</body>
</html>

        login.html文件,内容如下

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>title</title>
</head>
<body>

<div>
    <form action="{% url 'xxx' %}" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="password" name="password">
        <input type="submit">
    </form>

</div>

</body>
</html>

        urls.py里面的内容:

from django.shortcuts import render,httpresponse,redirect

def index(request):
    return render(request,'index.html',{'name':'ce'})

def login(request):
    method = request.method
    
    if method == 'get':
        return render(request,'login.html')
    else:
        username = request.post.get('username')
        password = request.post.get('password')
        if username == 'ce' and password == '123':
            return redirect('/index/')  #重新定向到/index/路径,这也是发送了一个请求,
别忘了在上面引入这个redirect类,和render,httpresponse在同一个地方引入 else: return httpresponse('失败')

    上面几个文件搞好之后,我们重启django项目,然后登陆页面的输入网址,注意,你输入的网址端口要和你启动的django项目的端口一样。

  但是如果我们在函数里面写的render来返回内容,两者有什么不同呢?

from django.shortcuts import render,httpresponse,redirect

# create your views here.

def index(request):

    return render(request,'index.html',{'name':'chao'})

def login(request):
    method = request.method

    if method == 'get':
        return render(request,'login.html')
    else:
        username = request.post.get('username')
        password = request.post.get('password')
        if username == 'chao' and password == '123':
            return redirect('/index/')    #重定向到/index/路径,这也是发送一个请求,别忘了在上面引入这个redirect类,和render,httpresponse在一个地方引入
            #如果直接用render来返回页面,是一次响应就返回来页面,两者是有区别的,如果你用render返回index.html页面,那么这个页面里面的模板渲染语言里面需要的数据你怎么搞,如果这些数据就是人家index那个函数里面独有的呢,你怎么搞,有人可能就响了,我把所有的数据都拿过来不就行了吗,首先如果数据量很大的话,是不是都重复了,并且你想想如果用户登陆完成之后,你们有进行跳转,那么如果网速不太好,卡一下,你想刷新一下你的页面,你是不是相当于又发送了一个login请求,你刷新完之后,是不是还要让你输入用户名和密码,你想想是不是,所有咱们一般在登陆之后都做跳转。
            #redirect本质上也是一个httpresponse的操作,看看源码就知道了
            # return httpresponse('success')
        else:
            return httpresponse('失败')