基于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模块功能全都以你写的表为准