diff --git a/MONACO.TTF b/MONACO.TTF new file mode 100644 index 0000000..57217b3 Binary files /dev/null and b/MONACO.TTF differ diff --git a/app_admin/check_code.py b/app_admin/check_code.py new file mode 100644 index 0000000..9760f3f --- /dev/null +++ b/app_admin/check_code.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# coding:utf-8 +# 生成验证码图片 +import random +from PIL import Image, ImageDraw, ImageFont, ImageFilter + +_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z +_upper_cases = _letter_cases.upper() # 大写字母 +_numbers = ''.join(map(str, range(3, 10))) # 数字 +init_chars = ''.join((_letter_cases, _upper_cases, _numbers)) + +def create_validate_code(size=(120, 30), + chars=init_chars, + img_type="GIF", + mode="RGB", + bg_color=(255, 255, 255), + fg_color=(0, 0, 255), + font_size=18, + font_type="MONACO.TTF", + length=4, + draw_lines=True, + n_line=(1, 2), + draw_points=True, + point_chance = 2): + ''' + @todo: 生成验证码图片 + @param size: 图片的大小,格式(宽,高),默认为(120, 30) + @param chars: 允许的字符集合,格式字符串 + @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG + @param mode: 图片模式,默认为RGB + @param bg_color: 背景颜色,默认为白色 + @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF + @param font_size: 验证码字体大小 + @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf + @param length: 验证码字符个数 + @param draw_lines: 是否划干扰线 + @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效 + @param draw_points: 是否画干扰点 + @param point_chance: 干扰点出现的概率,大小范围[0, 100] + @return: [0]: PIL Image实例 + @return: [1]: 验证码图片中的字符串 + ''' + + width, height = size # 宽, 高 + img = Image.new(mode, size, bg_color) # 创建图形 + draw = ImageDraw.Draw(img) # 创建画笔 + + def get_chars(): + '''生成给定长度的字符串,返回列表格式''' + return random.sample(chars, length) + + def create_lines(): + '''绘制干扰线''' + line_num = random.randint(*n_line) # 干扰线条数 + + for i in range(line_num): + # 起始点 + begin = (random.randint(0, size[0]), random.randint(0, size[1])) + #结束点 + end = (random.randint(0, size[0]), random.randint(0, size[1])) + draw.line([begin, end], fill=(0, 0, 0)) + + def create_points(): + '''绘制干扰点''' + chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100] + + for w in range(width): + for h in range(height): + tmp = random.randint(0, 100) + if tmp > 100 - chance: + draw.point((w, h), fill=(0, 0, 0)) + + def create_strs(): + '''绘制验证码字符''' + c_chars = get_chars() + strs = ' %s ' % ' '.join(c_chars) # 每个字符前后以空格隔开 + + font = ImageFont.truetype(font_type, font_size) + font_width, font_height = font.getsize(strs) + + draw.text(((width - font_width) / 3, (height - font_height) / 3), + strs, font=font, fill=fg_color) + + return ''.join(c_chars) + + if draw_lines: + create_lines() + if draw_points: + create_points() + strs = create_strs() + + # 图形扭曲参数 + params = [1 - float(random.randint(1, 2)) / 100, + 0, + 0, + 0, + 1 - float(random.randint(1, 10)) / 100, + float(random.randint(1, 2)) / 500, + 0.001, + float(random.randint(1, 2)) / 500 + ] + img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲 + + img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强(阈值更大) + + return img, strs \ No newline at end of file diff --git a/app_admin/urls.py b/app_admin/urls.py index 0221ffc..9980227 100644 --- a/app_admin/urls.py +++ b/app_admin/urls.py @@ -10,4 +10,5 @@ urlpatterns = [ path('project_manage/',views.admin_project,name='project_manage'), # 文集管理 path('doc_manage/',views.admin_doc,name='doc_manage'), # 文集管理 path('doctemp_manage/',views.admin_doctemp,name='doctemp_manage'), # 文集管理 + path('check_code/',views.check_code,name='check_code'), # 验证码 ] \ No newline at end of file diff --git a/app_admin/views.py b/app_admin/views.py index 5c7fbc3..cddb7ac 100644 --- a/app_admin/views.py +++ b/app_admin/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render,redirect -from django.http.response import JsonResponse +from django.http.response import JsonResponse,HttpResponse from django.contrib.auth import authenticate,login,logout # 认证相关方法 from django.contrib.auth.models import User # Django默认用户模型 from django.contrib.auth.decorators import login_required # 登录需求装饰器 @@ -9,6 +9,18 @@ import json import datetime from app_doc.models import * +# 返回验证码图片 +def check_code(request): + import io + from . import check_code as CheckCode + + stream = io.BytesIO() + # img图片对象,code在图像中写的内容 + img, code = CheckCode.create_validate_code() + img.save(stream, "png") + # 图片页面中显示,立即把session中的CheckCode更改为目前的随机字符串值 + request.session["CheckCode"] = code + return HttpResponse(stream.getvalue()) # 登录视图 def log_in(request): @@ -48,6 +60,7 @@ def register(request): username = request.POST.get('username',None) email = request.POST.get('email',None) password = request.POST.get('password',None) + checkcode = request.POST.get("check_code",None) if username and email and password: if '@'in email: email_exit = User.objects.filter(email=email) @@ -61,11 +74,27 @@ def register(request): elif len(password) < 6: errormsg = '密码必须大于等于6位!' return render(request, 'register.html', locals()) + elif checkcode != request.session['CheckCode'].lower(): + errormsg = "验证码错误" + return render(request, 'register.html', locals()) else: - pass + # 创建用户 + user = User.objects.create_user(username=username, email=email, password=password) + user.save() + # 登录用户 + user = authenticate(username=username, password=password) + if user.is_active: + login(request, user) + return redirect('/') + else: + errormsg = '用户被禁用!' + return render(request, 'register.html', locals()) else: errormsg = '请输入正确的电子邮箱格式!' return render(request, 'register.html', locals()) + else: + errormsg = "请检查输入值" + return render(request, 'register.html', locals()) # 注销 diff --git a/db.sqlite3 b/db.sqlite3 index 1a58837..a02c0b8 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/template/app_doc/pro_list.html b/template/app_doc/pro_list.html index 4f013a6..b1e8f8b 100644 --- a/template/app_doc/pro_list.html +++ b/template/app_doc/pro_list.html @@ -55,9 +55,12 @@
作者:{{p.create_user}}
+简介:{{ p.intro }}
+