自定义用户
写一个继承自AbstractUser的类,然后追加自己需要的字段在settings.py加入AUTH_USER_MODEL = 'app的名字.用户类'
自定义用户认证
步骤在app的目录下新键一个文件 auth.py写一个继承自ModeBackend复写authenticate函数(一个是找人,一个是校验密码)在settings.py里设置:AUTHENTICATION_BACKENDS="app的名字.文件名字.类"
使用和原生认证是一样的
例子:
用户的登录,注册不做了,使用Django shell创建一个用户登录:用户名 手机号写一个测试用户是否登录的API
自定义认证类的具体实现
1 找人1.1 使用用户名搜索1.2 再按照电话号搜索2 校验密码如果通过,返回user对象 否则返回Nonefrom django.contrib.auth.backends import ModelBackendfrom .models import MyUserclass MyBackend(ModelBackend):def authenticate(self, request, username=None, password=None, **kwargs):# 找人print("进入函数")try:user = MyUser.objects.get(username=username)print("没找到")except Exception:try:user = MyUser.objects.get(phone=username)print(user.username, "找到了")except Exception as e:print(username, e)return Noneprint("拿到用户",user.username)# 密码校验if user.check_password(password):return userelse:return None
自定义中间件
在中间件进行用户名的判断 满足条件直接返回
中间件应用: 我们可以做反爬虫,可以做日志统计,做错误统计,做缓存
实现:
from django.http import HttpResponse, HttpResponseForbiddenfrom django.utils.deprecation import MiddlewareMixinclass YJMiddleWare(MiddlewareMixin):def process_request(self, request):# name = request.GET.get("name")# if name == "tom":#return HttpResponse("恭喜获得特斯拉一辆")# elif name == "ada":#return HttpResponse("特斯拉模型一辆")# elif name == "班长":#return HttpResponse("咖妃")black_ips = ["124.160.17.98", "101.68.87.26"]# 获取IPip = request.META.get("REMOTE_ADDR")print(ip)if ip in black_ips:return HttpResponseForbidden("黑名单成员 无法访问")else:return HttpResponse("欢迎进入真人赌场,体验美女荷官")
在settings.py里加入
MIDDLEWARE = [。。。。'MiddleWares.MyAOP.YJMiddleWare' # 目录名.文件名.类名]
上传文件
在models.py
class Book(models.Model):name = models.CharField(max_length=40)icon = models.ImageField(upload_to="icons" # 指定文件保存的路径名 系统自动创建)
在settings.py 加入
配置上传文件目录MEDIA_ROOT = os.path.join(BASE_DIR, "static/uploads")
views.py
def create_book_v1(req):# 解析参数name = req.POST.get("name")myfile = req.FILES.get("icon")# 实例化一个数据book = Book.objects.create(name=name,icon=myfile)return HttpResponse("ok")
如果想访问图片 需要自己拼接url
book = Book.objects.all().first()# 拼接图片的网络路径icon_url = "http://{}/static/uploads/{}".format(req.get_host(), #获取访问的域名加端口book.icon.url #图片的路径字符串)
生成随机文件名
得到uuid字符串
实例化md5
md5进行加密
得到32位16进制的字符串
import uuidimport hashlibimport randomdef get_unique_str():# 得到一个uuid的字符串uuid_str = str(uuid.uuid4()).encode("utf-8")# 实例化md5md5 = hashlib.md5()# 进行加密md5.update(uuid_str)# 返回32位的十六进制数据return md5.hexdigest()
上传文件实现2
def create_book_v2(req):if req.method == "GET":return render(req, "mybook.html")else:# 拿到参数name = req.POST.get("name")myfile = req.FILES.get("icon")# 文件路径filename = get_unique_str() + "." + myfile.name.split(".")[-1]filepath = os.path.join(settings.MEDIA_ROOT, filename)f = open(filepath, "wb")print(filename)for i in myfile.chunks():f.write(i)f.close()return HttpResponse("ok")
文件上传到oss
用的阿里云
def upload_to_oss(req):import oss2endpoint = 'http://oss-cn-'access_key_id = 'LTA#########V9jSq'access_key_secret = '7uXYe##############AWFkxIw'bucket_name = 'share-msg'bucket_name_host = "share-##Bucket 域名##"# 生成一个认证对象auth = oss2.Auth(access_key_id, access_key_secret)bucket = oss2.Bucket(auth, endpoint, bucket_name)#获取文件f = req.FILES.get("icon")# StringIO BytesIOfrom io import BytesIO# 实例化iobuf = BytesIO()# 写入到内存for i in f.chunks():buf.write(i)#调整指针到开头buf.seek(0)# 上传filename = get_unique_str() + "." + f.name.split(".")[-1]bucket.put_object(filename, buf.getvalue())print(filename)file_url = "https://" + bucket_name_host + "/" + filename# 可以考虑把文件存到数据库return HttpResponse(file_url)
StringIO
在内存的缓冲中 操作数据 和操作文件是类似的 也有指针的概念
验证码
pip install Pillow
需要:画布 画笔 和字体
def get_confirm_code(req):from PIL import Image, ImageDraw, ImageFontfrom io import BytesIO#实例化一个画布img_size = (150,70)img_color = get_random_color()img = Image.new("RGB", img_size, img_color)#实例化一个画笔draw = ImageDraw.Draw(img)code_xy = (20, 20)# code_color = (0, 255, 0)# 实例化一个字体font_path = os.path.join(settings.STATICFILES_DIRS[0], "fonts/ADOBEARABIC-BOLD.OTF")font_size = 30font = ImageFont.truetype(font_path, font_size)# 画一个字母# draw.text(code_xy,"L", font=font, fill=code_color)# draw.text(code_xy, "O", font=font, fill=code_color)source = "zxcvbnmasdfghjklqwertyuiop1234567890ZXCVBNMASDFGHJKLQWERTYUIOP"# 用来保存 我们生成的随机字符res = ""for i in range(4):#随机出一个字母code_color = get_random_color()index = random.randint(0, len(source))my_str = source[index]res += my_strdraw.text((20+30*i, 20), my_str, fill=code_color, font=font)# 画点for i in range(100):x = random.randint(0, 150)y = random.randint(0, 70)draw.point((x, y), fill=get_random_color())# width = random.randint(0, 100)# draw.line((20, 65), fill=(255, 255, 255), width=50)buf = BytesIO()# 保存img.save(buf, "png")del draw# 保存的sessionreq.session["verify_code"] = resreturn HttpResponse(buf.getvalue(), content_type="image/png")
应用
def my_login_v1(req):if req.method == "GET":return render(req, "my_login.html")else:code = req.POST.get("code")server_code = req.session.get("verify_code")# 将用户传入的和系统session保存的字符都转小写 然后做比较if code and len(code) > 0 and code.lower() == server_code.lower():return HttpResponse("ok")else:return HttpResponse("no ok")
前端:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="/jquery/1.10.2/jquery.min.js"></script><script>$(function () {$("#myimg").click(function () {console.log("调用")$(this).attr("src", "/t06/img" + Math.random());})})</script></head><body><form action="/t06/my_login" method="post">{% csrf_token %}<img src="/t06/img" alt="" id="myimg"><br><input type="text" name="code" placeholder="请输入验证码(忽略大小写)"><br><input type="submit" value="验证"></form></body></html>