Django 之 视图层

文章目录

    • 视图层
    • HttpRequest对象
      • request对象的属性
    • HttpResponse对象
    • CBV和FBV
      • FBV版
      • CBV版
      • FBV的装饰器
      • CBV的装饰器

视图层

一个视图就是Python的一个函数。这个函数第一个参数的类型是HttpRequest;它返回一个HttpResponse实例。为了使一个Python的函数成为一个Django可识别的视图,它必须满足这两个条件。

视图函数的代码写哪里都可以,但一般约定俗成设置在项目或应用程序目录中的 views.py 文件中。下面是一个以HTML文档的形式返回当前日期和时间的视图:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "It is now %s." % now
    return HttpResponse(html)

让我们来逐行解释下上面的代码:

  • 首先,我们从 django.http模块导入了HttpResponse类,以及Python的datetime库。

  • 接着,我们定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request

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

  • 这个视图会返回一个HttpResponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象。

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

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

每个视图负责返回一个HttpResponse对象。

HttpRequest对象

django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的之外,其他均为只读的

request对象的属性

request.scheme:代表请求的方案,http或者https

request.path:请求的路径,比如请求127.0.0.1/org/list,那这个值就是/org/list

request.method:表示请求使用的http方法,GET或者POST请求

request.encoding:表示提交数据的编码方式

request.GET:获取GET请求

request.POST:获取post的请求,比如前端提交的用户密码,可以通过request.POST.get()来获取

request.COOKIES:包含所有的cookie

request.session:一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。

request.FILES:一个类似于字典的对象,包含所有的上传文件信息。 FILES 中的每个键为 中的name,值则为对应的数据。

注意,FILES 只有在请求的方法为POST 且提交的

带有enctype=“multipart/form-data” 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象。另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中

包含所有的cookie

request.user:一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。

如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。把request传给前端的时候,前端可以通过 {% if request.user.is_authenticated %}判断用户时候登录

request.META:一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:

一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:

  • CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
  • CONTENT_TYPE —— 请求的正文的MIME 类型。
  • HTTP_ACCEPT —— 响应可接收的Content-Type。
  • HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
  • HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
  • HTTP_HOST —— 客服端发送的HTTP Host 头部。
  • HTTP_REFERER —— Referring 页面。
  • HTTP_USER_AGENT —— 客户端的user-agent 字符串。
  • QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
  • REMOTE_ADDR —— 客户端的IP 地址。
  • REMOTE_HOST —— 客户端的主机名。
  • REMOTE_USER —— 服务器认证后的用户。
  • REQUEST_METHOD —— 一个字符串,例如"GET""POST"
  • SERVER_NAME —— 服务器的主机名。
  • SERVER_PORT —— 服务器的端口(是一个字符串)

上传文件示例

def upload(request):
    """
    保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
    但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
    """
    if request.method == "POST":
        # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
        filename = request.FILES["file"].name
        # 在项目目录下新建一个文件
        with open(filename, "wb") as f:
            # 从上传的文件对象中一点一点读
            for chunk in request.FILES["file"].chunks():
                # 写入本地文件
                f.write(chunk)
        return HttpResponse("上传OK")

HttpResponse对象

响应对象主要有三种形式:

  • HttpResponse()
  • render()
  • redirect()

HttpResponse()

括号内直接跟一个具体的字符串作为响应体。

render()

render(request, template_name[, context])
参数:
     request: 用于生成响应的请求对象。
     template_name:要使用的模板的完整名称,可选的参数
     context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。

redirect()

传递要重定向的一个硬编码的URL

def my_view(request):
    ...
    return redirect('/index/')

也可以是一个完整的URL:

def my_view(request):
    ...
    return redirect('http://www.baidu.com/') 

JsonResponse对象

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

from django.http import JsonResponse
response = JsonResponse({'foo': 'bar'})
print(response.content)
b'{"foo": "bar"}'

默认能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。

response = JsonResponse([1, 2, 3], safe=False)

CBV和FBV

CBV基于类的视图(Class base view)和FBV基于函数的视图(Function base view)

FBV版

# FBV版添加班级
def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

CBV版

# CBV版添加班级
from django.views import View
class AddClass(View):
    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/")

注意:

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

# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),

FBV的装饰器

FBV本身就是一个函数,所以和给普通的函数加装饰器无差:

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("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

CBV的装饰器

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

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

#CBV版添加班级
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/")

使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。

class Login(View):
    def dispatch(self, request, *args, **kwargs):
        print('before')
        obj = super(Login,self).dispatch(request, *args, **kwargs)
        print('after')
        return obj
    def get(self,request):
        return render(request,'login.html')
    def post(self,request):
        print(request.POST.get('user'))
        return HttpResponse('Login.post')

实例:session的操作

你可能感兴趣的:(Django,Django,视图层,python)