自定义用户
写一个继承自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对象 否则返回None
from django.contrib.auth.backends import ModelBackend
from .models import MyUser
class 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 None
print("拿到用户",user.username)
# 密码校验
if user.check_password(password):
return user
else:
return None
自定义中间件
在中间件进行用户名的判断 满足条件直接返回
中间件应用: 我们可以做反爬虫,可以做日志统计,做错误统计,做缓存
实现:
from django.http import HttpResponse, HttpResponseForbidden
from django.utils.deprecation import MiddlewareMixin
class 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"
]
# 获取IP
ip = request.META.get("REMOTE_ADDR")
print(ip)
if ip in black_ips:
return HttpResponseForbidden("黑名单成员 无法访问")
else:
return HttpResponse("欢迎进入真人赌场,体验美女荷官")
在settings.py里加入
MIDDLEWARE = [
。。。。
'MiddleWares.MyAOP.YJMiddleWare' # 目录名.文件名.类名
]
上传文件
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")
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 uuid
import hashlib
import random
def get_unique_str():
# 得到一个uuid的字符串
uuid_str = str(uuid.uuid4()).encode("utf-8")
# 实例化md5
md5 = 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 oss2
endpoint = 'http://oss-cn-shanghai.aliyuncs.com'
access_key_id = 'LTA#########V9jSq'
access_key_secret = '7uXYe##############AWFkxIw'
bucket_name = 'share-msg'
bucket_name_host = "share-##Bucket 域名##ncs.com"
# 生成一个认证对象
auth = oss2.Auth(access_key_id, access_key_secret)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
#获取文件
f = req.FILES.get("icon")
# StringIO BytesIO
from io import BytesIO
# 实例化io
buf = 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, ImageFont
from 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 = 30
font = 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_str
draw.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
# 保存的session
req.session["verify_code"] = res
return 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="http://libs.baidu.com/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>