DjangoBBS项目功能拆分
1、随机验证码
url(r'^get_code/', views.get_code, name='get_code'),
# 获取随机3个0-255数
def get_random():
"""
:return: 返回0-255三个随机数,元组
"""
return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
# 获取验证码
def get_code(request):
# 1.产生一张随机颜色的图片
img_obj = Image.new('RGB', (350, 35), get_random())
# 2.产生一只在图片上的画笔
img_draw = ImageDraw.Draw(img_obj)
# 3.产生字体样式
img_font = ImageFont.truetype(r'static\font\font.ttf', 35)
io_obj = BytesIO()
# 产生5个随机验证码
code = ''
for i in range(5):
upper_str = chr(random.randint(65, 90)) # 大写字母
lower_str = chr(random.randint(97, 122)) # 小写字母
random_int = str(random.randint(0, 9)) # 数字
# 随机取一个
temp_str = random.choice([upper_str, lower_str, random_int])
# 写在图片上,位置,内容,颜色,字体
img_draw.text((45 + i * 60, -2), temp_str, get_random(), font=img_font)
# 储存
code += temp_str
print(code)
img_obj.save(io_obj, 'png')
request.session['code'] = code
return HttpResponse(io_obj.getvalue())
前端代码:
<img src="/get_code/" alt="图片验证码" id="id_img">
js代码:
原理:src改变,立马刷新。点击一次图片,给url添加一个?号
$('#id_img').click(function () {
var oldSrc = $(this).attr('src');
$(this).attr('src', oldSrc += '?')
});
2、注册功能
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.bootcss.com/sweetalert/2.0.0/sweetalert.min.js"></script>
<link rel="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.min.css">
{% load static %}
<link rel="stylesheet" href="{% static '/bootstrap-3.3.7-dist/css/bootstrap.min.css'%}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<h2 class="text-center">注册页面</h2>
<div class="col-md-8 col-md-offset-2">
<form id="myform">
{% csrf_token %}
{% for form in form_obj %}
<div class="form-group">
<label for="{{ form.id_for_label }}">{{ form.label }}</label>
{{ form }}
<span style="color: red" class="pull-right"></span>
</div>
{% endfor %}
<div class="form-group">
<label for="id_avatar">头像
<img src="/static/images/default.jpg" alt="" width="100" style="margin-left: 10px" id="id_img">
</label>
<input type="file" name="myfile" id="id_avatar">
</div>
<a href="/login/"><input type="button" value="登录" class="btn btn-success pull-left"></a>
<input type="button" value="注册" class="btn btn-danger" id="id_submit">
</form>
</div>
</div>
</div>
<script>
$('#id_avatar').change(function () {
// 1 先获取用户上传的头像文件
var avatarFile = $(this)[0].files[0];
// 2 利用文件阅读器对象
var myFileReader = new FileReader();
// 3 将文件交由阅读器对象读取
myFileReader.readAsDataURL(avatarFile);
// 4 修改img标签的src属性 等待文件阅读器对象读取文件之后再操作img标签
myFileReader.onload = function(){
$('#id_img').attr('src',myFileReader.result)
}
});
// 点击按钮触发ajax提交动作
$('#id_submit').on('click',function () {
// 1 先生成一个内置对象 FormData
var myFormData = new FormData();
// 2 添加普通键值对
{#console.log($('#myform').serializeArray())#}
$.each($('#myform').serializeArray(),function (index,obj) {
myFormData.append(obj.name,obj.value)
});
// 3 添加文件数据
myFormData.append('avatar',$('#id_avatar')[0].files[0]);
// 4 发送数据
$.ajax({
url:'',
type:'post',
data:myFormData,
// 两个关键性参数
contentType:false,
processData:false,
success:function (data) {
if (data.code===1000){
// 注册成功之后 应该跳转到后端返回过来的url
location.href = data.url
}else{
$.each(data.msg,function(index,obj){
// 1 先手动拼接字段名所对应的input框的id值
var targetId = '#id_' + index; // #id_username
// 2 利用id选择器查找标签 并且将div标签添加报错类
$(targetId).next().text(obj[0]).parent().addClass('has-error')
})
}
}
})
});
$('input').focus(function () {
// 移除span标签内部的文本 还需要移除div标签的class中has-error属性
$(this).next().text('').parent().removeClass('has-error')
})
</script>
</body>
</html>
后端urls.py:
# 注册
url(r'^register/', views.register, name='register'),
views.py:
# 注册
def register(request):
form_obj = MyRegForm()
if request.method == 'POST':
back_dic = {'code': 1000, 'msg': ""}
# 校验用户名、密码
form_obj = MyRegForm(request.POST)
if form_obj.is_valid():
# 用变量接收正确的结果 clean_data = {'username' 'password' 're_password' 'email'}
clean_data = form_obj.cleaned_data
# 将确认密码键值对删除,表中没有re_password
clean_data.pop('re_password')
# 把签名、用户CSS名字存进Blog表中
sign = clean_data.get('sign')
username = clean_data.get('username')
site_theme = username + '.css'
models.Blog.objects.create(site_name=username, site_title=sign, site_theme=site_theme)
# 添加字段
clean_data['blog'] = models.Blog.objects.filter(site_name=username).first()
clean_data.pop('sign')
# 额外做的事情:给每个新的注册用户添加3个默认的分类和3个默认的标签
create_list = []
blog = models.Blog.objects.filter(site_name=username).first()
for i in ['一', '二', '三']:
category_name = username+'的分类'+i
create_list.append(models.Category(name=category_name, blog=blog))
models.Category.objects.bulk_create(create_list)
# 添加3个默认标签
create_list = []
for i in ['一', '二', '三']:
tag_name = username + '的标签' + i
create_list.append(models.Tag(name=tag_name, blog=blog))
models.Tag.objects.bulk_create(create_list)
# 获取用户头像文件
avatar_obj = request.FILES.get('avatar')
# 判断用户头像文件是否为空,用户没有上传
if avatar_obj:
# 用户上传了,添加到clean_data中
clean_data['avatar'] = avatar_obj # clean_data = {'username' 'password' 'email' 'avatar'}
models.UserInfo.objects.create_user(**clean_data) # 打散传入 ??=??的形式
back_dic['msg'] = '注册成功'
back_dic['url'] = '/login/'
else:
back_dic['code'] = 2000
back_dic['msg'] = form_obj.errors
return JsonResponse(back_dic)
return render(request, 'register.html', locals())
myforms.py:
from django import forms
from app01 import models
class MyRegForm(forms.Form):
username = forms.CharField(min_length=3,max_length=8,label='用户名',
error_messages={
"min_length":'用户名最短3位',
"max_length":'用户名最长8位',
"required":'用户名不能为空',
},widget=forms.widgets.TextInput(attrs={'class':'form-control'})
)
password = forms.CharField(min_length=3, max_length=8, label='密码',
error_messages={
"min_length": '密码最短3位',
"max_length": '密码最长8位',
"required": '密码不能为空',
}, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
re_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
error_messages={
"min_length": '确认密码最短3位',
"max_length": '确认密码最长8位',
"required": '确认密码不能为空',
}, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(label='邮箱',
error_messages={
"required": '邮箱不能为空',
"invalid":"邮箱格式不正确"
},
widget=forms.widgets.EmailInput(attrs={'class': 'form-control'})
)
sign = forms.CharField(min_length=5, max_length=15, label='学习宣言',
error_messages={
"min_length": '学习宣言最短5位',
"max_length": '学习宣言最长15位',
"required": '学习宣言不能为空',}
, widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
)
# 钩子函数
# 局部钩子校验用户名是否已存在
def clean_username(self):
username = self.cleaned_data.get('username')
is_alive = models.UserInfo.objects.filter(username=username)
if is_alive:
self.add_error('username','用户名已存在')
return username
# 全局钩子校验密码与确认密码是否一致
def clean(self):
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if not password == re_password:
self.add_error('re_password','两次密码不一致')
return self.cleaned_data
3、登录功能
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.bootcss.com/sweetalert/2.0.0/sweetalert.min.js"></script>
<link rel="https://cdn.bootcss.com/sweetalert/1.1.3/sweetalert.min.css">
{% load static %}
<link rel="stylesheet" href="{% static '/bootstrap-3.3.7-dist/css/bootstrap.min.css'%}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">登录页面</h2>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="id_username">用户名</label>
<input type="text" name="username" class="form-control" id="id_username">
</div>
<div class="form-group">
<label for="id_password">密码</label>
<input type="password" name="password" class="form-control" id="id_password">
</div>
<div class="form-group">
<label for="id_code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" name="code" class="form-control" id="id_code">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="图片验证码" id="id_img">
</div>
</div>
</div>
<input type="button" value="登录" class="btn btn-success" id="id_submit">
<a href="/register/"><input type="button" value="注册" class="btn btn-danger"></a>
<span style="color: red" id="error"></span>
</div>
</div>
</div>
<script>
$('#id_img').click(function () {
var oldSrc = $(this).attr('src');
$(this).attr('src', oldSrc += '?')
});
$('#id_submit').click(function () {
$.ajax({
url:'',
type:'post',
data:{
'username': $('#id_username').val(),
'password': $('#id_password').val(),
'csrfmiddlewaretoken':'{{ csrf_token }}',
'code':$('#id_code').val()
},
success:function (data) {
if (data.code === 1000){