day59小结

基于django中间件拷贝思想

​ 例如通知功能:
​ 邮件
​ 短信
​ 微信
​ · · ·

关于importlib模块

import importlib
res = 'lib.bbb'  # 利用字符串的形式导入模块
md = importlib.import_module(res)  # from lib import bbb
print(md)  # 该模块字符串最小单位只能到文件名
# <module 'lib.bbb' from 'E:\python12期\test\lib\bbb.py'>

通知文件notify(鸭子类型)

class Email(object):
    def __init__(self):
        pass  # 发送邮件需要的前期准备
    
    def send(self,content):
        print('邮件通知:%'%scontent)
class Msg(object):
    def __init__(self):
        pass  # 发送短信需要的前期准备
    
    def send(self,content):
        print('短信通知:%'%scontent)
class WeChat(object):
    def __init__(self):
        pass  # 发送微信需要的前期准备
    
    def send(self,content):
        print('微信通知:%'%scontent)

_init_ 文件

import settings
import importlib
def send_all(content):
    for path in settings.NOTIFY_LIST:  # "notify.email.Email"
        module_path,cls_name = path.rsplit(',',maxsplit=1)
        md = importlib.import_module(module_path)  # from notify import email
        cls = getattr(md,cls_name)  # 获取到文件中类的名字
        obj = cls()  # 实例化产生一个个类的对象
		obj.send(content)

settings

NOTIFY_LIST = [
    'notify.email.Email',
    'notify.msg.Msg',
    'notify.wechat.WeChat'
]

启动文件

from notify import *

send_all('好嗨哦')

这样需要添加功能只需要在notify文件添加功能 再在settings文件中添加路径字符串即可 若要删除某个功能只需要注释对应的路径字符串即可

跨站请求伪造csrf

​ 钓鱼网站
​ 你自己写一个跟中国银行正规网站一模一样的页面
​ 用户输入用户名 密码 对方账户 转账金额提交
​ 请求确实是朝中国银行的接口发送的 钱也扣了
​ 但是对方账户变了 变成了钓鱼网站自己提前设置好的账户

​ 如何实现
​ 你在写form表单的时候 让用户填写的对方账户input并没有name属性
​ 而是你自己在内部偷偷隐藏了一个具有name属性的input框
​ 并且value值是你自己的账户 然后将该标签隐藏了

​ 模拟该现象的产生
​ 创建两个django项目

​ 如何解决该问题
​ 只处理本网站发送的post请求

​ 如何识别判断当前请求是否是本网站发出的

​ 解决
​ 网站在返回给用户一个form表单的时候会自动在表单隐藏一个input框
​ 这个框的value是一个随机字符串 但是网站能够基础每一个浏览器发出的随机字符串

​ 你以后在写form表单的时候 你只需要在表单中写一个{% csrf_token %}

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>target_account:<input type="text" name="target_user"></p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>
<input type="hidden" name="csrfmiddlewaretoken" value="rJ47FeK9T55wavvVJGY6UxdM1kTMHhTqotGfaXjXIK8Ahz2Uvs02yR9T8bBn5q2D">

​ ajax如何解决
​ 1.方式一 较为繁琐
​ 先在页面任意的位置上书写{% csrf_token %}
​ 然后在发送ajax请求的时候 通过标签查找获取随机字符串添加到data自定义对象即可
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()}

​ 2.方式二 较为简单
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},

​ 3.方式3 官方提供的文件 最为通用的一种方式
​ 直接兴建js文件拷贝代码 导入即可
​ 你不需要做任何的csrf相关的代码书写
​ 参考:django

csrf相关的两个装饰器

from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt  # 不校验 csrf
def index(request):
    return HttpResponse('index')

@csrf_protect  # 校验
def login(request):
    return HttpResponse('login')

在FBV中跟普通的装饰器一样

这两个装饰器在CBV上的差异

# @method_decorator(csrf_exempt,name='post')  # csrf_exempt不支持该方法
@method_decorator(csrf_exempt,name='dispatch')  # csrf_exempt
class MyIndex(views.View):
    # @method_decorator(csrf_exempt)  # 可以
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self,request):
        return render(request,'transfer.html')
    # @method_decorator(csrf_exempt,name='post')  # csrf_exempt不支持该方法
    def post(self,request):
        return HttpResponse('OK')		
    # csrf_exempt这个装饰器只能给dispatch装才能生效
    
"""
csrf_protect方式全都可以  跟你普通的装饰器装饰CBV一致
"""
# @method_decorator(csrf_protect,name='post')  # 可以
class MyIndex(views.View):
    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self,request):
        return render(request,'transfer.html')
    # @method_decorator(csrf_protect)  # 可以
    def post(self,request):
        return HttpResponse('OK')

django settings源码剖析

​ django有两个配置文件
​ 一个是暴露给用户可以配置的

​ 一个是内部全局的(用户配置亏了就用用户的 用户没有配就用自己的)

from django.conf import global_settings  # 导入django默认settings文件

​ obj
​ obj.name = 'egon' # 全局
​ obj.name = 'jason' # 局部

​ 先加载全局配置 给对象设置
​ 然后在加载局部配置 再给对象设置
​ 一旦有重复的项 后者覆盖前者

auth模块简介

​ 如何创建超级用户(root)
python3 manage.py createsuperuser

auth模块常用方法

1.创建用户

from django.contrib.auth.models import User
# User.objects.create(username=username,password=password)  # 不可用  密码不是加密的
# User.objects.create_user(username=username,password=password)  # 创建普通用户    密码自动加密
# User.objects.create_superuser(username=username,password=password,email='123@qq.com')  # 创建超级用户   需要邮箱数据

2.校验用户名和密码是否正确

from django.contrib import auth
user_obj = auth.authenticate(request,username=username,password=password)
# 必须传用户名和密码两个参数缺一不能

3.保存用户状态

auth.login(request,user_obj)
# 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象

4.判断用户登录状态

auth.loginv.is_authenticated()
# 只要这句话执行了 后面在任意位置 只要你能拿到request你就可以通过request.user获取到当前登录的用户对象

5.校验原密码是否正确

request.user.check_password(old_password)

6.修改密码

request.user.set_password(new_password)
request.user.save()  # 千万不要忘了

7.注销

auth.logout(request)

8.校验用户是否登录装饰器

from django.contrib.auth.decorators import login_required
局部配置
@login_required(login_url='/login/')  # 指定没有登陆跳转的页面
def index(request):
    pass
全局配置
settings配置文件中 直接配置
LOGIN_URL = '/login/'
@login_required
def index(request):
    pass
# 如果全局配置了 局部也配置  以局部的为准

auth扩展表

​ 方式一 利用外键一对一做扩展

class UserDetail(models.Model):
    phone = models.BigIntegerField()
    user = models.OneToOneField(to='User')

​ 方式二 利用继承关系

from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):
    phone = models.BigIntegerField()
    register_time = models.DateField(auto_now_add=True)

    # 一定要注意 还需要去配置文件中配置
    AUTH_USER_MODEL = 'app01.Userinfo'  # 应用名.表名
    # 这么写完之后 之前所有的auth模块功能全都以你写的表为准

原文地址:https://www.cnblogs.com/LZF-190903/p/12008398.html