Django View视图

视图view

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

无论视图本身包含什么逻辑,都要返回响应。大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

  • Django使用请求Request和响应Response来给整个系统传递状态
  • 当用户请求一个页面时,Django创建一个包含元数据和请求内容的HttpRequest对象。然后Django加载适当的视图,HttpRequest对象作为视图函数的第一个参数,每个视图负责返回一个HttpResponse对象。
from django.http import HttpResponse

def show(req):
    name = 'Jerry'
    content = '<h1>hello %s!</h1>' % name
    return HttpResponse(content)

 首先从 django.http模块导入了HttpResponse类。然后定义了show函数。它就是视图函数;每个视图函数的第一个参数都为request,其实是一个HttpRequest对象。视图函数中封装了一个HTML格式的字符串,传入HttpResponse()后,实例化一个HttpResponse对象并返回。

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

HttpRequest对象

对象属性

HttpRequest.scheme:字符串(http/https)表示http还是https请求

HttpRequest.body:原始的http请求主体

HttpRequest.path:完整的请求路径,不包括域

HttpRequest.method:请求中使用的HTTP方法(GET/POST)

HttpRequest.encoding:请求的字符集

HttpRequest.GET:类似字典的对象,包含所有给定的HTTP GET参数

HttpRequest.POST:类似字典的对象,包含所有给定的HTTP POST参数,前提是请求包含表单数据。

HttpRequest.COOKIES:客户端cookies信息,字典类型

HttpRequest.FILES:一个包含所有文件对象的字典. key是<inputtype="file" name="" />中name的值,每一个value是一个上传的文件对象,如果要上传文件需要在 <form> 标签中添加 enctype="multipart/form-data",不然收到的是一个空值

HttpRequest.META:请求的META属性

HttpRequest.headers:一个不区分大小写的类似dict的对象,包含请求中所有HTTP加前缀的标题的访问

def index(request):

    print(request.scheme)  #http
    print(request.body)  #b''
    print(request.path)  #/app/
    print(request.method)  #GET
    print(request.encoding)  #None
    print(request.GET)  #<QueryDict: {'name': ['aaa']}>
    print(request.POST)  #<QueryDict: {}>
    print(request.META.get('CONTENT_TYPE'))  #text/plain
    print(request.META.get('REMOTE_ADDR'))  #127.0.0.1
    print(request.headers.get('Connection'))  #keep-alive
    print(request.headers.get('Accept-Encoding'))  #gzip, deflate, br

    return HttpResponse('<h1>hello</h1>')
HttpRequest属性

对象方法

HttpRequest.get_host():返回当前服务器的IP和端口

HttpRequest.get_port():返回当前服务器原始端口

HttpRequest.get_full_path():返回附加查询的请求路径

HttpRequest.is_secure():如果返回True,请求时安全的,也就是https协议

HttpRequest.is_ajax():是否为ajax请求

def index(request):

    print(request.get_host())  #127.0.0.1:8000
    print(request.get_port())  #8000
    print(request.get_full_path())  #/app/?name=aaa
    print(request.is_secure())  #False
    print(request.is_ajax())  #False

    return HttpResponse('<h1>hello</h1>')
HttpRequest方法

HttpResponse对象

对象属性

HttpResponse.content:表示内容的字节字符串,如果需要,从字符串编码。

HttpResponse.charset:一个字符串,表示将在其中编码响应的字符集。如果未在HttpResponse实例化时间给出,则将从中提取 content_type,如果不成功,DEFAULT_CHARSET则将使用该 设置。

HttpResponse.status_code:该响应的HTTP状态代码。除非reason_phrase明确设置,否则修改 status_code构造函数外部的值也会修改值reason_phrase。

HttpResponse.reason_phrase:响应的HTTP原因短语。它使用了HTTP标准的默认原因短语。除非明确设置,否则reason_phrase由status_code的值确定。

对象方法

HttpResponse.__init__(content = b'', content_type=None, status=200, reason=None, charset=None)

使用给定的页面内容和内容类型实例化对象。

  • content:最常见的是迭代器,字节串或字符串。其他类型将通过编码其字符串表示形式转换为bytestring。
  • content_type:是可选的字符集编码完成的MIME类型,用于填充HTTP Content-Type标头。
  • status:响应的HTTP状态代码。
  • reason:HTTP响应短语。如果未提供,将使用默认短语。
  • charset:编码响应的字符集。如果没有给出,它将从中提取content_type,如果不成功,DEFAULT_CHARSET将使用该设置。

HttpResponse.set_cookie(key, value, max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False, samesite=None):设置一个cookie。

HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False, samesite=None):在对cookie设置之前进行签名加密,加密后的cookie中的键值对将是密文的;获取cookie信息时也要使用相对应方法HttpRequest.get_signed_cookie()。

HttpResponse.delete_cookie(key,path ='/',domain = None):使用给定的key删除对应的cookie,path、domain应该指定和set_cookie()时相同的值。

render()

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

def render(request, template_name, context=None, content_type=None, status=None, using=None):
    """
    Return a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

必需参数:

  • request:用于生成此响应的HttpRequest对象;
  • template_name:要使用的模板的完整名称;

可选参数:

  • context:添加到模板上下文的一个字典,默认是一个空字典, 通过它可以向模板传入自定义参数,视图将在渲染模板之前调用它;
  • content_type:生成的文档要使用的MIME类型.,默认为DEFAULT_CONTENT_TYPE设置的值"text/html";
  • status:响应的状态码. 默认为200;
  • useing:用于加载模板的模板引擎的名称。
from django.shortcuts import render

def my_view(request):
    active = True
    return render(request, 'index.html', {'name': active}, content_type='application/xhtml+xml')

redirect()

默认返回一个临时的重定向,传递permanent=True可以返回一个永久的重定向。临时重定向(响应状态码: 302)和永久重定向(响应状态码: 301)对普通用户来说是没什么区别的, 它主要面向的是搜索引擎的机器人。

def redirect(to, *args, permanent=False, **kwargs):
    """
    Return an HttpResponseRedirect to the appropriate URL for the arguments
    passed.
    """
    redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    return redirect_class(resolve_url(to, *args, **kwargs))

参数可以是:

  • 一个模型: 将调用模型的get_absolute_url()函数
  • 一个视图, 可以带有函数: 可以使用urlresolvers.reverse来反向解析名称
  • 一个绝对的或相对的URL, 将原封不动的作为重定向的位置
from django.shortcuts import redirect

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

def my_view(request):
    return redirect('https://example.com/')

Cookie、Session

浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。

但有时候用户需要保持登陆状态,或者一些。 实现会话保持主要有两种方式:cookie和session。

Cookie

Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。通常情况下,它用于判断两个请求是否来自同一个浏览器 - 例如,保持用户登录。它记住无状态HTTP协议的有状态信息。

Cookie主要用于三个目的:

  1. 会话管理,登录,购物车,游戏分数或服务器应记住的任何其他内容;
  2. 个性化,用户首选项,主题和其他设置;
  3. 跟踪,记录和分析用户行为。

特点

cookie数据保存在客户端,以key-value存储;

cookie有过期时间,默认关闭浏览器过期;

cookie是基于域名安全的;

当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器。

Session

session是存储在后端数据库中的键值对,django生成一个随机字符串sessionid作为key,用户的信息作为value;

当浏览器第一次发送请求时,服务器会生成与用户相关的session,然后将在sessionid放入cookie中返回给浏览器,浏览器会将此cookie保存在本地;之后每次请求时浏览器都会将这个cookie发给服务器,服务器在提取到sessionid后,会根据这个随机字符串去数据库中找出这个请求者的信息。

特点

session数据保存在服务器,以key-value存储;

session依赖于cookie,每个客户端的session信息标识保存在客户端cookie中;

session也有过期时间,django中session过期时间默认2周,flask开启session过期时间之后默认30天;

在视图中使用cookie

HttpResponse.set_cookie(key, value, max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False, samesite=None)

设置一个cookie

  • key、value:设置cookie中的键值,都是字符串类型;
  • max_age:一个整数,表示在指定秒数后过期;
  • expires:一个datetime或timedelta对象,会话将在这个指定的日期/时间过期;可以不设置,django会根据max_age自动设置;
  • path:指定一个路径,只有在这个路径下才可以访问到cookie;
  • domain:如果你想设置一个跨域的cookie。例如, domain="example.com"将设置域www.example.com,blog.example.com等可读的cookie。否则,cookie只能由设置它的域读取;
  • Secure:https协议访问;
  • httponly:如果为True,就阻止客户端的JavaScript操作cookie。
def login(request):
    re = redirect('/app/index.html')  #实例一个redirect HttpResponse对象
    re.set_cookie('username', username, max_age=20)  #为对象设置cookie信息
    return re  #返回HttpResponse对象)

HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False, samesite=None):在对cookie设置之前进行签名加密,加密后的cookie中的键值对将是密文的;获取cookie信息时也要使用相对应方法HttpRequest.get_signed_cookie();

HttpRequest.COOKIES.get(key, None):通过请求对象的COOKIES属性获取;

HttpRequest.get_signed_cookie(key):获取加密cookie的方法;

HttpResponse.delete_cookie(key,path ='/',domain = None):使用给定的key删除对应的cookie,path、domain应该指定和set_cookie()时相同的值。

在视图中使用session

当SessionMiddleware激活时,每个HttpRequest 对象 - 任何Django视图函数的第一个参数,将具有一个 session属性,这是一个类似字典的对象。request.session可以在视图中的任何位置查看编辑它。

backends.base.SessionBase类是所有的session对象的基类;它具有标准的字典方法

# 设置session
request.session[key] = value
request.session.setdefault(key, value)

# 修改session
request.session[key] = value

# 将新的字典更新进去
request.session.update(dicts)

# 获取session
request.session.get(key)
request.session.keys()
request.session.values()
request.session.items()

# 设置过期时间
request.session.set_expiry()
# 获取过期时间、日期
request.session.get_expiry_age()
request.session.get_expiry_date()
# 是否关闭浏览器时session过期
request.session.get_expire_at_browser_close()
# 从数据库存储中删除过期的会话
request.session.clear_expired()

# 删除指定key
del request.session[key]
request.session.pop(key)

# 清空session,不会删除数据库
request.session.clear()
# 删除session_key的session数据,删除数据库
request.session.delete(session_key=None)
request.session.flush()

# 创建一个key唯一的新的session对象,并保存
request.session.create()

# 保存session数据,如果must_create = True则创建新session
request.session.save(must_create=False)

# 创建新的session_key,同时保留当前session数据
request.session.cycle_key()

# 加载session,返回一个字典
request.session.load()

# 如果session为空,返回True
request.session.is_empty()

# 如果session_key已存在,则返回True
request.session.exists(session_key)

# 包含sessionid的属性
request.session.session_key

# 通过modified属性可以明确告诉session对象它已经被修改
request.session.modified = True
session对象方法

基于类的视图

使用基于类的视图

views.py

from django.shortcuts import render, redirect
from . import models
from django import views

class Login(views.View):
    # 重写get()方法,前端get请求执行此方法
    def get(self, request, *args, **kwargs):
        return render(request, 'myapp/login.html')

    # 重写post()方法,前端post请求执行此方法
    def post(self, request, *args, **kwargs):
        # 从前端请求获取用户信息
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 从数据库中获取与用户信息相同的对象个数
        user_auth = models.Administrator.objects.filter(username=username, password=password).count()
        # 如果用户信息验证通过
        if user_auth:
            # 设置session
            request.session['username'] = username
            request.session['password'] = password
            request.session['active'] = True
            # 实例化重定向对象
            httpresponse = redirect('/app/index.html')
            # 返回重定向
            return httpresponse
        else:
            # 用户验证不通过,返回错误信息
            login_error = '登陆失败'
            return render(request, 'myapp/login.html', {'login_error': login_error})
基于view类的用户登陆

当使用类封装view函数后,在URLconf中将配置类属性as_view() 作为参数来调用。

当一个请求到达的 URL 被关联模式匹配时,这个类方法返回一个函数。这个函数创建一个类的实例,调用 setup() 初始化它的属性,然后调用 dispatch() 方法。观察请求并决定它是GET和POST

from django.contrib import admin
from django.urls import path, include, re_path
from myapp.views import Login

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'login.html$', Login.as_view()),
]
urls.py

装饰类

类上的方法与独立函数完全不同,因此不能应用函数装饰器到方法上,需要先将它转换为方法装饰器。method_decorator装饰器转换函数。

假设需要定义两个装饰器,可以把两个装饰器防入list中,然后传入method_decorator()中。

from django.shortcuts import render, redirect
from django import views
from django.utils.decorators import method_decorator

def is_login(f):
    def inner(request, *args):
        # 获取请求中的session信息
        username = request.session.get('username')
        # 如果存在session信息,返回执行函数
        if username:
            return f(request, *args)
        # 如果不存在则跳转至登陆页面
        else:
            return redirect('/login.html')
    return inner

class Index(views.View):
    @method_decorator(is_login)
    def get(self, request):
        session = request.session.get('username')
        return render(request, 'myapp/index.html', {'user': session})
方法前装饰器

也可以直接把装饰器加在类上,然后参数name指定被装饰的方法

@method_decorator(is_login, name='get')
class Index(views.View):
    def get(self, request):
        session = request.session.get('username')
        return render(request, 'myapp/index.html', {'user': session})
类前装饰器

如果一个类的所有的请求方法都需要加装饰器,可以直在dispatch方法前添加;因为当请求到达时,会先调用dispatch方法,判断请求方法,再去调用对应的方法。

class Index(views.View):
    @method_decorator(is_login)
    def dispatch(self, request, *args, **kwargs):
        #返回父类dispatch方法结果
        return super().dispatch(request, *args, **kwargs)

    def get(self, request):
        session = request.session.get('username')
        print(session)
        return render(request, 'myapp/index.html', {'user': session})
dispatch

 

posted @ 2019-06-28 14:22  houyongchong  阅读(212)  评论(0编辑  收藏  举报