day 59
01.importlib 模块
- 利用字符串导入模块
- 只能写到文件名为止,不能写内部的变量名
- 利用反射解决变量名问题
01.基于django中间件的思想实现功能配置
-
以模块的方式导入
# notify.py def send_email(content): print('邮箱通知:%s'%content) def send_msg(content): print('短信通知:%s'%content) def send_wechat(content): print('微信通知:%s'%content) # start.py from notify import * def send_all(content): send_msg(content) send_email(content) send_wechat(content) if __name__ == '__main__': send_all('再坚持一天就周末了')
-
以配置文件的形式
# settings.py NOTIFY_LIST = [ 'notify.email.Email', 'notify.msg.Msg', 'notify.wechat.WeChat', 'notify.qq.Qq', ]
import settings import importlib def send_all(content): for path in settings.NOTIFY_LIST: # 循环获取列表中的所有字符串 module_path, cls_name = path.rsplit('.',maxsplit=1) # 将字符串形式的文件对象和类名分开 md = importlib.import_module(module_path) # 获取到文件对象 cls = getattr(md,cls_name) # 通过反射获取到类名 obj = cls() # 实力化产生一个个类的对象 obj.send(content) # 调用按照鸭子类型写好的同类功能
02.跨站请求伪造csrf
-
钓鱼网站原理
- 模仿正规网站页面,提前写好一些隐藏好的数据
-
解决
-
form表单
{% csrf_token %}
-
ajax请求
-
方式一
- 在页面上书写
{% csrf_token %}
- 在发送ajax请求时使用标签查找,携带上该数据
- 在页面上书写
-
方式二
'csrfmiddlewaretoken':'{{ csrf_token }}'
会自动显示该标签的value
-
方式三
-
直接使用官网提供的脚本文件,直接以js脚本文件的形式导入
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
<!-- 直接在页面下方导入 --> <script src="/static/setup.js"></script>
-
-
-
-
csrf相关装饰器
- csrf_exempt;不校验csrf
- csrf_protect;校验csrf
- 两个装饰器在CBV上的区别
- csrf_exempt只能使用装饰在dispatch上
- csrf_protect和正常的装饰器一样
03.auth模块
auth模块时django自带的用户认证模块,默认使用auth_user表啊来存储用户数据
-
如何创建超级用户(root)
- python3 manage.py createsuperuser
- 会自动给密码加密
-
操作auth_user表
-
创建用户
from django.contrib.auth.models import User create_user() # 创建普通用户 create_superuser() # 创建超级用户 # 创建的用户密码会自动加密
-
校验用户名和密码是否正确(必须传用户名和密码两个参数)authenticate
obj = auth.authenticate(request,username=username,password=password) # 会自动将密码加密后验证,成功会返回数据对象
-
保存用户登录状态 login
from django.contrib import auth auth.login(request,obj) # 会在后端生成相应的session数据 # 只要执行了这句话,后面在任意位置只要能拿到request你就可以request.user获取到当前登录的用户对象
-
判断当前用户是否登录
request.user.is_authenticated() # 返回布尔值
-
登录装饰器
# 登录装饰器,用来校验当前用户是否登录 # 局部配置 @login_reqired(login_url='/login/') def index(request): pass # 全局配置 settings配置文件中 LOGIN_URL = '/login/' @login_reqired def index(request): pass
-
校验密码
request.user.check_password(password) # 单独判断密码是否正确
-
修改密码
request.user.set_password(password) request.user.save() # 修改之后一定要保存
-
退出登录
auth.logout(request) # 会自动将session值删掉
-
auth_user扩展字段
-
方式一;利用外键一对一作扩展
class UserDetail(models.Model): phone = models.BigIntegerField() user = models.OneToOneField(to='User')
-
方式二;利用面向对象的继承
-
继承AbstractUser
from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): phone = models.CharFied
-
在配置文件中修改auth模块指定表
AUTH_USER_MODEL = 'app01.UserInfo' # 应用名.表名 # 所有的auth功能以这个表为准
-
只能在项目新创建时进行修改,执行数据库迁移命令之前
-
-
04.如何将django中settings的思想应用到自己的项目中
- diango中有两个配置文件
- 一个是暴露给用户配置的
- 一个是内部全局的(一旦用户配置了,就是用用户的,否则使用全局的)
- 在加载配置时先加载全局的在加载用户的,一旦有重复的用户配置,会覆盖掉全局的
# lib.conf.__init__.py import importlib from lib.conf import global_settings import os class Settings(object): def __init__(self): for name in dir(global_settings): if name.isupper(): k = name v = getattr(global_settings,name) setattr(self,k,v) # 加载全局配置 module_path = os.environ.get('xxx') md = importlib.import_module(module_path) for name in dir(md): if name.isupper(): k = name v = getattr(md,name) setattr(self,k,v) # 加载用户配置
# lib.conf.global_settings.py NAME = '我是项目默认的配置文件' # conf.settings.py NAME = '我是用户自定义配置文件'
# start.py import os import sys BASE_DIR = os.path.dirname(__file__) sys.path.append(BASE_DIR) if __name__ == '__main__': # os.environ.setdefault('xxx','conf.settings') os.environ['xxx'] = 'conf.settings' # 效果相同 from lib.conf import settings print(settings.NAME)
-