python开发框架——Django基础知识(六)


  hello!我是小J,每天一个小知识,一起学python,让技术无限发散。

1. 类视图

①什么是类?

类(Class)是面向对象程序设计(Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。

这里的类和python基础里的类有一样的理解:有相同特性和行为的对象的抽象就是类

②类的三大特性

  • 封装性,将数据和操作封装为一个有机的整体,由于类中私有成员都是隐藏的,只向外部提供有限的接口,所以能够保证内部的高内聚性和与外部的低耦合性。
  • 继承性,更符合认知规律,使程序更易于理解,同时节省不必要的重复代码。
  • 多态性,是指同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向父类(基类)的指针,来调用实现子类(派生类)中的方法。

1.1 类视图的编写

在类视图的编写这一部分,类的编写和注意事项与python基础的类的编写遵循同样的规则,在类的命名时通常类名的首字母大写(或使用大驼峰命名,做到见文知意)

路由

from django.urls import path
from django.urls import re_path
from . import views
app_name = 'books'
urlpatterns = [
    # 类视图
    path('register',views.RegisterView.as_view()),
]

错误编码

from django.views import View

# 类视图
# View 继承了as_view() 这个方法里面就指定了请求的方式
class RegisterView(View):
    def index(self,request):
        return HttpResponse('class view')

通过http://127.0.0.1:8000/register访问,发现出现错误
在这里插入图片描述

  这里就不得不说一下类视图中定义请求方法名的不同了,在类视图中,请求方法名的命名已经被固定了下来,在定义类视图的请求方法名时应该遵循类视图方法名的定义规则,我们定义的类视图是继承自django.views的View,View()继承了as_view() 这个方法里面就指定了请求的方式。我们来看一View的源码就理解了:

class View:
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in kwargs.items():
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError(
                    'The method name %s is not accepted as a keyword argument '
                    'to %s().' % (key, cls.__name__)
                )
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

在源码中的as_view()已经规定了请求方法名有:

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

所以在类视图中的请求方法名只能采用上述几种
正确编码

class RegisterView(View):
    def get(self,request):
        return HttpResponse('class view')

再次通过http://127.0.0.1:8000/register访问
在这里插入图片描述

1.2 状态码

  HTTP状态码是用以表示网页服务器超文本传输协议响应状态的3位数字代码。它由 RFC 2616 规范定义的,并得到 RFC 2518、RFC 2817、RFC 2295、RFC 2774 与 RFC 4918 等规范扩展。所有状态码的第一个数字代表了响应的五种状态之一。所示的消息短语是典型的,但是可以提供任何可读取的替代方案。

  • 200 - 成功 服务器已经成功处理了请求,这表示服务器提供了请求的网页。
  • 202 - 已接受 服务器已接受请求,但尚未处理。
  • 203 - 非授权信息 服务器已经成功处理了请求,但返回的信息可能来自别的资源
  • 204 - 无内容 服务器成功处理了请求,但没有返回任何内容。
  • 300 - 多种选择 针对请求,服务器可执行多种操作
  • 304 - 未修改 自上次请求后,请求的网页未修改过
  • 400 - 错误请求 服务器不理解请求的语法
  • 403 - 禁止 服务器拒绝请求
  • 404 - 未找到 服务器到不到请求的网页
  • 500 - 服务器内部错误 服务器遇到错误,无法完成请求

更多的状态码可以参考:https://blog.csdn.net/weixin_48031311/article/details/112705868

class RegisterView(View):
    def get(self,request):
        return HttpResponse('class view')

    def post(self,request):
        pass

通过http://127.0.0.1:8000/register/
在这里插入图片描述
在这里插入图片描述

1.3 类试图的注册功能

类视图的注册功能首先要求我们先在根目录下创建一个模型(template)文件夹
在这里插入图片描述
然后在项目的setting.py文件中的TEMPLATESd下的’DIRS’中进行模板文件夹的路径配置

在这里插入图片描述
在template中新建一个名为index3.html的文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<form action="#" method="post">
    username : <input type="text" id="username" name="username"><br>
    password : <input type="password" id="password" name="password"><br>
    register : <button type="submit">注册</button>

</form>
</body>
</html>

然后丰富我们前面编写的视图类,在这里,使用的是render()来渲染模板,render()的参数介绍:

render(request, template_name, context=None, content_type=None,
status=None, using=None)

  • request: 是一个固定参数

  • template_name: templates中定义的文件,注意路径名。比如:“templates/index3.html”, 则参数这样写:“index3.html”

  • context: 要传入文件中用于渲染呈现的数据, 默认是字典格式

  • content_type: 生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值。

  • status: http的响应代码,默认是200.

  • using: 用于加载模板使用的模板引擎的名称。

class RegisterView(View):
    def get(self,request):
        # render()渲染网页
        return render(request,'index3.html')

    def post(self,request):
        # 获取数据
        print(request)
        # return HttpResponse('success')
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username)
        print(password)
        return JsonResponse({'username':username,'password':password})

最后运行项目,通过http://127.0.0.1:8000/register/访问网页,
在这里插入图片描述
输入用户名和密码进行表单的提交

username:admin
password:123456
在这里插入图片描述
在这里插入图片描述

1.4 类视图中的装饰器

需要写一个很符合我个性的一个装饰器,如下

# 装饰器
def my_decorator(func):
    def wrapper(request,*args,**kwargs):
        print('自定义的装饰器')
        print('请求路径%s'%request.path)
        return func(request,*args,**kwargs)
    return wrapper

然后,怎样将我们这个很有个性的装饰器 应用到我们的视图中,这显然又有一点门道,我这儿有两招可以供诸君挑选。
①在子路由文件中修改我们的路由

# 导入新的包
from .views import my_decorator
app_name = 'books'
urlpatterns = [
    # 类视图  类视图装饰器
    # 原路由 path('register/',views.RegisterView.as_view(),name='register'),
	# 更改后的路由
   path('register/',my_decorator(views.RegisterView.as_view()),name='register'),
]

通过http://127.0.0.1:8000/register/访问网页,实现结果:
在这里插入图片描述
在这里插入图片描述
可以看到我们实现了这个很有个性的装饰器,但是不得不吐槽的就是这终端中打印的啥东西啊,我只想用一次装饰器,结果给我用那么多次,真的是以为自己是电脑就不需要电费啦!这远远满足不了我们的需求,只能给它升级一下

②导入的django中的包来帮助我们,路由用原路由

  • method_decorator的使用:
    name:这个参数是必备的,是为了装饰类中的get方法还是post方法
from django.views import View
from django.utils.decorators import method_decorator
# 类视图
# View 继承了as_view() 这个方法里面就指定了请求的方式
class RegisterView(View):
    @method_decorator(my_decorator)
    def get(self,request):
        # render()渲染网页
        return render(request,'index3.html')

    def post(self,request):
        # 获取数据
        print(request)
        # return HttpResponse('success')
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username)
        print(password)
        return JsonResponse({'username':username,'password':password})

通过http://127.0.0.1:8000/register/,结果展示:
在这里插入图片描述
在这里插入图片描述
咦!终端中只使用了一次这个很个性的装饰器,可以满足我的需求了,可见添加上述代码后结局了后顾之忧

2. 中间件

中间件是Django请求/响应处理的钩子框架,以类的形式体现,属于轻量级的、低级的插件系统,用于全局改变django的输入或输出。
在这里插入图片描述

2.1 激活中间件

激活中间件时,我们需要将自定义的中间件类添加到项目中setting.py文件中MIDDLEWARE的列表中。我这儿激活了自定义的middlewarse.out1,middlewarse.out2

MIDDLEWARE = [
    # 就是对安全的访问处理,把http请求重新定向到https
    'django.middleware.security.SecurityMiddleware',
    # 用的request.session
    'django.contrib.sessions.middleware.SessionMiddleware',
    # 检测 是否允许浏览器的类型
    'django.middleware.common.CommonMiddleware',
    # 跨域请求伪造中间件,如果不注释它,在提交表单的时候必须要加 csrf_token
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'books.middlewarse.out1',  # 注册自定义的中间件
    'books.middlewarse.out2',  # 注册自定义的中间件
    # 中间件的执行顺序:先调用最下面的这个中间件,再先从上往下执行
]

2.2 中间件请求和响应

在请求阶段,调用views前,django会按照MIDDLEWARE_CLASSES中定义的顺序从上到下调用中间件。Django的中间可以分为从上到下的hooks和从下到上的hooks。

从上到下hooks:

  • process_request()
  • process_view()

从下到上的hooks:

  • process_exception()
  • process_template_response()
  • process_response()

在这里插入图片描述

2.3 中间件的hooks说明

一个中间件最少有一个process_request hooks和一个process_response hooks,前者用来处理请求,后者用来处理响应。
在这里插入图片描述

2.4 中间件的处理顺序

  1. process_request阶段
    发起一个请求后,该请求会从上往下经过上述所有的中间件并先执行所有中间件中的process_request()方法,如果该方法返回HttpResponse,则会执行process_response(),如果返回None,则会向下继续执行process_request

  2. process_view阶段
    请求执行完所有的process_request方法后,都返回None,就会执行process_view方法,如果有一个process_view方法返回HttpResponse,会跳过下一个process_view方法,直接从下往上执行process_response,如果process_view方法返回None,会继续向下执行

  3. view阶段
    当请求执行完所有的process_request和process_view仍返回None,会到达views视图函数,在这里会出现三种情况
    在这里插入图片描述

  4. process_response 阶段
    当 process_request, process_view,views,process_template_response,process_exception 方法都执行完成后,开始自下而上从中间件中执行 process_response 方法,直到最上层中间件的 process_response 方法执行完毕
    在这里插入图片描述

2.5 自定义中间件

def out1(func):
    print('调用1')
    def inner(*args,**kwargs):
        print('执行1')
        return func(*args,**kwargs)
    return inner

def out2(func):
    print('调用2')
    def inner(*args,**kwargs):
        print('执行2')
        return func(*args,**kwargs)
    return inner

结果:
在这里插入图片描述

2.6 CSRF

Django 为用户实现防止跨站请求伪造的功能,通过中间件django.middleware.csrf.CsrfViewMiddleware来完成。

全局中间件:

MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
]

局部中间件:
编写一个简单的index4.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>crsf</title>
</head>
<body>
<form method="get">
    <p>hahahahaha</p>
</form>
</body>
</html>
  1. FBV模式局部使用:
  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。需要注释这一句话’django.middleware.csrf.CsrfViewMiddleware’,
from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_protect
def csrf_test(request):
    if request.method == 'GET':
        return render(request,'index4.html')
    else:
        return HttpResponse('ok')
  • 路由 path('csrf_test/',views.csrf_test)

  • 通过http://127.0.0.1:8000/csrf_test/,结果:
    在这里插入图片描述

  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。不需要注释这一句话’django.middleware.csrf.CsrfViewMiddleware’,

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def csrf_test1(request):

    if request.method == 'GET':
        return render(request,'index4.html')
    else:
        return HttpResponse('ok')
  • 路由 path('csrf_test1/', views.csrf_test),

  • 通过http://127.0.0.1:8000/csrf_test1/,结果
    在这里插入图片描述

  1. CBV模式局部使用:
  • 局部禁用:在dispatch()方法上面添加 @csrf_exempt
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.shortcuts import render, HttpResponse
from django.views import View
class CsrfViews(View):
    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return HttpResponse('GET,success')

    def post(self, request, *args, **kwargs):
        return HttpResponse('Post,success')
  • 路由 :path('csrfviews/',views.CsrfViews.as_view()),

  • 通过http://127.0.0.1:8000/csrfviews/ ,结果:
    在这里插入图片描述

  • 局部使用:同样在dispatch()方法上添加django内置装饰器@method_decorator,将csrf_protect传入:

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.shortcuts import render, HttpResponse
from django.views import View
class CsrfViews1(View):
    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return HttpResponse('GET,success')

    def post(self, request, *args, **kwargs):
        return HttpResponse('Post,success')

  • 路由: path('csrfviews1/',views.CsrfViews1.as_view()),
  • 通过http://127.0.0.1:8000/csrfviews1/ ,结果:
    在这里插入图片描述

2.7 表单提交数据

通过FORM表单提交:在form表单里面需要加{% csrf_token %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<form action="#" method="post">
    {% csrf_token %}
    username : <input type="text" id="username" name="username"><br>
    password : <input type="password" id="password" name="password"><br>
    register : <button type="submit">注册</button>

</form>
</body>
</html>
  • 路由:path('register/',views.RegisterView.as_view(),name='register'),
  • 通过:http://127.0.0.1:8000/register/ ,结果:
    在这里插入图片描述
    当用户访问/register/页面的时候,会自动生成一个csrf随机字符串,并且cookie中也存放这个随机字符串,当用户再次提交数据的时候会带的这个随机字符串提交。
    在这里插入图片描述

更多中间件可参考:https://docs.djangoproject.com/en/2.1/ref/middleware/


结束语

  本文属于作者原创,转载请注明出处,不足之处,希望大家能过给予宝贵的意见,如有侵权,请私信。每天一个小知识,一起学python,让技术无限发散
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python独角兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值