BBS登录与注册功能的总结
BBS登录与注册功能的总结
一、表设计:表名 外键字段
表名 models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""用户表"""
phone = models.BigIntegerField(verbose_name='手机号',null=True)
avatar = models.FileField(upload_to='avatar/',default='avatar/default.jpg',verbose_name='用户头像')
register_time = models.DateTimeField(verbose_name='注册时间',auto_now_add=True)
site = models.OneToOneField(to='Site',on_delete=models.CASCADE,null=True)
class Site(models.Model):
"""个人站点表"""
site_name = models.CharField(verbose_name='站点名称',max_length=32)
site_title = models.CharField(verbose_name='站点标题',max_length=32)
site_theme = models.CharField(verbose_name='站点样式',max_length=32,null=True)
class Article(models.Model):
"""文章表"""
title = models.CharField(verbose_name='文章标题',max_length=32)
desc = models.CharField(verbose_name='文章简介',max_length=255)
content = models.TextField(verbose_name='文章内容')
create_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
# 三个优化字段
comment_num = models.IntegerField(verbose_name='评论数',default=0)
up_num = models.IntegerField(verbose_name='点赞数',default=0)
down_num = models.IntegerField(verbose_name='点踩数',default=0)
# 外键表
site = models.ForeignKey(to='Site',on_delete=models.CASCADE,null=True)
category = models.ForeignKey(to='Category',on_delete=models.CASCADE,null=True)
tags = models.ManyToManyField(to='Tag',through='Article2Tag',through_fields=('article', 'tag'),
null=True)
class Category(models.Model):
"""文章分类表"""
name = models.CharField(verbose_name='分类名称',max_length=32)
site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)
class Tag(models.Model):
"""文章标签表"""
name = models.CharField(verbose_name='标签名称',max_length=32)
site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)
class Article2Tag(models.Model):
"""多对多外键表"""
article = models.ForeignKey(to='Article',on_delete=models.CASCADE,null=True)
tag = models.ForeignKey(to='Tag',on_delete=models.CASCADE,null=True)
class UpAndDown(models.Model):
"""文章点赞点踩表"""
user = models.ForeignKey(to='UserInfo',on_delete=models.CASCADE,null=True)
article = models.ForeignKey(to='Article',on_delete=models.CASCADE,null=True)
is_up = models.BooleanField(verbose_name='点赞点踩数')
class Comment(models.Model):
"""文章评论表"""
user = models.ForeignKey(to='UserInfo',on_delete=models.CASCADE,null=True)
article = models.ForeignKey(to='Article',on_delete=models.CASCADE,null=True)
content = models.TextField(verbose_name='评论内容')
comment_time = models.DateTimeField(auto_now_add=True,verbose_name='评论时间')
parent = models.ForeignKey(to='self',on_delete=models.CASCADE,null=True) # 自关联字段
url.py
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('register/',views.register_func,name='register_view'),
# 用户登录功能
path('login/',views.login_func,name='login_view'),
# 图片验证码
path('get_code/',views.get_code_func)
]
views.py
from django.shortcuts import render,HttpResponse,redirect
from app import myforms
from app import models
from django.http import JsonResponse
from django.contrib import auth
def register_func(request):
# 前后端ajax交互,通常采用字段作为交互对象
back_dict = {'code':10000,'msg':''}
# 1.先产生一个空的form_obj
form_obj = myforms.RegisterForm()
if request.method == 'POST':
form_obj = myforms.RegisterForm(request.POST)
if form_obj.is_valid():
clean_data = form_obj.cleaned_data # 存储符合校验的数据
# 将confirm_password键值对移除
clean_data.pop('confirm_password')
# 获取用户上传的头像文件
avatar_obj = request.FILES.get('avatar') # 用户有可能没有上传
if avatar_obj:
clean_data['avatar'] = avatar_obj
# 创建用户数据
models.UserInfo.objects.create_user(**clean_data)
back_dict['msg'] = '注册成功'
back_dict['url'] = '/login/'
else:
back_dict['code'] = 10001
back_dict['msg'] = form_obj.errors
return JsonResponse(back_dict)
return render(request,'registerPage.html',locals())
def login_func(request):
back_dict = {'code': 10000, 'msg': ''}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
code = request.POST.get('code')
if code.upper() == request.session.get('code').upper():
user_obj = auth.authenticate(request, username=username, password=password)
if user_obj:
# 保存用户登录状态
auth.login(request, user_obj) # 执行之后就可以使用request.user获取登录用户对象
back_dict['msg'] = '登录成功'
back_dict['url'] = '/home/'
else:
back_dict['code'] = 10001
back_dict['msg'] = '用户名或密码'
else:
back_dict['code'] = 10002
back_dict['msg'] = '验证码错误'
return JsonResponse(back_dict)
return render(request, 'loginPage.html')
from PIL import Image,ImageFont,ImageDraw
from io import BytesIO,StringIO
"""
BytesIO 在内存中临时存储 读取的时候以bytes格式为准
StringIO 在内存中临时存储 读取的时候以字符串格式为准
"""
import random
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
def get_code_func(request):
# 产生图片对象
img_obj = Image.new('RGB',(350,35),get_random())
# 将图片交给画笔对象
draw_obj = ImageDraw.Draw(img_obj)
# 确定字体的样式
font_obj = ImageFont.truetype('static/font/111.ttf',35)
# 产生随机验证码
code = ''
for i in range(5):
random_upper = chr(random.randint(65,90))
random_lower = chr(random.randint(97,122))
random_int = str(random.randint(1,9))
# 三选一
temp_choice = random.choice([random_upper,random_lower,random_int])
# 写到图片上
draw_obj.text((i * 60 + 45,0),temp_choice,font=font_obj)
code += temp_choice
# 后端保存验证码
request.session['code'] = code
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
loginPage.html
Title
{% load static %}
用户登录
{% csrf_token %}
{% load static %}
用户注册
{% csrf_token %}
{% for form in form_obj %}
{{ form }}
{% endfor %}
</div>
<input type="button" id="subBtn" class="btn btn-primary btn-block" value="注册">
</form>
</div>
</div>
myforms.py
from django import forms
from app import models
class RegisterForm(forms.Form):
"""用户注册form类"""
username = forms.CharField(min_length=3,max_length=8,label='用户名',
error_messages={
'min_length':'用户名最短三位',
'max_length':'用户名最长八位',
'required':'用户名不能为空',
},
widget=forms.widgets.TextInput(attrs={'class':'form-control'})
)
password = forms.CharField(min_length=3, max_length=8, label='密码',
error_messages={
'min_length': '密码最短三位',
'max_length': '密码最长八位',
'required': '密码不能为空',
},
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
error_messages={
'min_length': '密码最短三位',
'max_length': '密码最长八位',
'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'})
)
# 局部钩子校验用户名是否已经存在
def clean_username(self):
username = self.cleaned_data.get('username')
res = models.UserInfo.objects.filter(username=username)
if res:
self.add_error('username','用户名已存在')
return username
# 全局钩子校验两次密码是否一致
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password','两次密码不一致')
return self.cleaned_data
重点代码的记忆
# 局部钩子校验用户名是否已经存在
def clean_username(self):
username = self.cleaned_data.get('username')
res = models.UserInfo.objects.filter(username=username)
if res:
self.add_error('username','用户名已存在')
return username
# 全局钩子校验两次密码是否一致
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password','两次密码不一致')
return self.cleaned_data
def register_func(request):
# 前后端ajax交互 通常采用字段作为交互对象
back_dict = {'code': 10000, 'msg': ''}
# 1.先产生一个空的form_obj
form_obj = myforms.RegisterForm()
if request.method == "POST":
form_obj = myforms.RegisterForm(request.POST) # username password confirm_password email csrfmiddlewaretoken
if form_obj.is_valid():
clean_data = form_obj.cleaned_data # 存储符合校验的数据 {username password confirm_password email}
# 将confirm_password键值对移除
clean_data.pop('confirm_password') # {username password email}
# 获取用户上传的头像文件
avatar_obj = request.FILES.get('avatar') # 用户有可能没有上传
if avatar_obj:
clean_data['avatar'] = avatar_obj # {username password email avatar }
# 创建用户数据
models.UserInfo.objects.create_user(**clean_data) # 上述处理字典的目的就是为了创建数据省事
back_dict['msg'] = '注册成功'
back_dict['url'] = '/login/'
else:
back_dict['code'] = 10001
back_dict['msg'] = form_obj.errors
return JsonResponse(back_dict)
return render(request, 'registerPage.html', locals())
登录注册关键代码比较
# 登录框的编写
<div class="container">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">用户登录</h2>
{% csrf_token %}
<div class="form-group">
<label for="name">用户名</label>
<input type="text" id="name" class="form-control" name="username">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" class="form-control" name="password">
</div>
<div class="form-group">
<label for="code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" id="code" class="form-control" name="code">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="" width="350" height="35" id="d1">
</div>
</div>
</div>
<input type="button" class="btn btn-success btn-block" value="登录" id="loginBtn">
</div>
</div>
# 登录按钮发送ajax请求
$('#loginBtn').click(function () {
// 可以再次使用form标签序列化功能 也可以自己挨个获取
$.ajax({
url:'',
type:'post',
data:{'username':$('#name').val(),'password':$('#password').val(), 'code':$('#code').val(),'csrfmiddlewaretoken':'{{ csrf_token }}'},
success:function (args) {
if (args.code === 10000){
window.location.href = args.url
}else {
swal(args.msg,'Here have a error')
}
}
})
})
# 注册框的编写
<div class="container">
<div class="col-md-8 col-md-offset-2">
<h2 class="text-center">用户注册</h2>
<form id="form">
{% csrf_token %}
{% for form in form_obj %}
<div class="form-group">
<label for="{{ form.auto_id }}">{{ form.label }}</label> <!--form.auto_id自动获取渲染的标签id值-->
{{ form }}
<span style="color: darkred" class="pull-right"></span>
</div>
{% endfor %}
<!--用户头像相关-->
<div class="form-group">
<label for="myfile">头像
<img src="/static/img/default.jpg" alt="" width="120" id="myimg">
</label>
<input type="file" id="myfile" style="display: none">
</div>
<input type="button" id="subBtn" class="btn btn-primary btn-block" value="注册">
</form>
</div>
</div>
# 1.用户头像的实时展示
$('#myfile').change(function () {
//1.产生一个文件阅读器
let myFileReaderObj = new FileReader();
//2.获取用户上传的头像文件
let fileObj = this.files[0];
// 3.将文件对象交给阅读器对象读取
myFileReaderObj.readAsDataURL(fileObj);
// 等待文件阅读器对象加载完毕之后再修改src
myFileReaderObj.onload = function () {
// 4.修改img标签的src属性展示图片
$('#myimg').attr('src', myFileReaderObj.result)
}
})
# 2.给注册的按钮绑定点击事件
$('#subBtn').click(function () {
//1.先产生一个内置对象
let myFormDataObj = new FormData();
//2.添加普通数据
$.each($('#form').serializeArray(),function (index,dataObj) { // 对结果for循环 然后交给后面的函数处理
myFormDataObj.append(dataObj.name,dataObj.value)
})
//3.添加文件数据
myFormDataObj.append('avatar',$('#myfile')[0].files[0])
//4.发送ajax请求
$.ajax({
url:'',
type:'post',
data:myFormDataObj,
contentType:false,
processData: false,
success:function (args) {
if (args.code === 10000){
window.location.href = args.url
}else {
let dataObj = args.msg;
// 针对性的渲染提示
$.each(dataObj,function (k,msgArray) {
//拼接标签的id值
let eleId = '#id_' + k
// 根据id查找标签 修改下面span标签的内容 并给父标签添加错误样式
$(eleId).next().text(msgArray[0]).parent().addClass('has-error')
})
}
}
})
})
# 3.给所有的input标签绑定获取焦点事件 移除错误样式
$('input').focus(function () {
$(this).next().text('').parent().removeClass('has-error')
})
效果图
BBS登录与注册功能的总结的更多相关文章
- BBS登录与注册功能
登录功能 视图函数 def my_login(request): if request.method == 'GET': return render(request, 'login.html') el ...
- AndroidStudio制作登录和注册功能的实现,界面的布局介绍
前言 大家好,给大家带来AndroidStudio制作登录和注册功能的实现,界面的布局介绍的概述,希望你们喜欢 每日一句: Success is connecting with the world a ...
- VS连接SQL Server 2008,并实现登录和注册功能
--------------------- 作者:Cambridge 来源:CSDN 原文:https://blog.csdn.net/cambridgeacm/article/details/797 ...
- 基于struts2和hibernate的登录和注册功能——完整实例
1.该项目使用MySQL数据库,数据库名为test,表名info,如图所示: 2.配置web.xml(Struts2使用) <?xml version="1.0" encod ...
- 用java集合模拟登录和注册功能
package com.linkage.login; import java.util.HashMap;import java.util.Iterator;import java.util.Map;i ...
- 用java数组模拟登录和注册功能
package com.linkage.login; import java.util.Scanner; public class user { // 存储用户名和密码 public static S ...
- JavaWeb 实现简单登录、注册功能
1.首先创建一个简单的动态Javaweb项目 2.然后手动建立文件目录: 项目创建好之后,在src下建几个包: controller:控制器,负责转发请求,对请求进行处理,主要存放servlet: d ...
- Unity uGUI 登录及注册功能
上次我们已经完成了登录界面的模拟功能,今天咱们把上次没做完的继续完善下!那么废话少说直接开始吧! PS:本次完善的功能有: 1,增加对数据库的操作. 2,使用了MD5Key值加密 3,完善登录和组测功 ...
- 利用PHP实现登录与注册功能以及使用PHP读取mysql数据库——以表格形式显示数据
登录界面 <body><form action="login1.php" method="post"><div>用户名:&l ...
随机推荐
- 沁恒CH32V003F4P6 开发板上手报告和Win10环境配置
CH32V003 沁恒最近推出的低价CH32V003系列, 基于青稞RISC-V2A内核, 48MHz主频, 2KB SRAM, 16KB Flash, 工作电压兼容3.3V和5V. 主要参数如下 S ...
- .NET API 接口数据传输加密最佳实践
.NET API 接口数据传输加密最佳实践 我们在做 Api 接口时,相信一定会有接触到要给传输的请求 body 的内容进行加密传输.其目的就是为了防止一些敏感的内容直接被 UI 层查看或篡改. 其实 ...
- 驱动开发:内核封装WSK网络通信接口
本章LyShark将带大家学习如何在内核中使用标准的Socket套接字通信接口,我们都知道Windows应用层下可直接调用WinSocket来实现网络通信,但在内核模式下应用层API接口无法使用,内核 ...
- ES6 学习笔记(一)let、const与作用域
一.let命令 1.1用法 1.1.1 let类似于var,但所声明的变量只在let命令所在的代码块有效. 如: { let a = 10 var b = 20 } console.log(b) co ...
- The Google File System 翻译和理解
The Google File System 摘要 GFS 是一个可扩展的分布式文件系统,用于大型分布式数据密集型应用上.它可以运行在便宜的普通硬件上,提供了高性能和一定的容错性. 1. 分布式文件系 ...
- 编码工具使用(go语言)
1.课程介绍 Git基础课程和实操 Goland介绍以及常用快捷键使用 Go delve 调试 你想要的linux 这里都有 2.版本控制工具介绍 原始的版本控制 修改文件,保存文件副本 版本控制的起 ...
- Referenced file contains errors (http://mybatis.org/dtd/mybatis-3-config.dtd). For more information, right click on the message in the Problems View and select "Show Details..."
mybatis配置文件报错Referenced file contains errors mybatis的配置文件报错 The errors below were detected when vali ...
- vscode+springboot+gradle
vscode+springboot+gradle 项目搭建 demo 目标:项目中抛弃所有xml格式文件 啰嗦: 一直在用maven作为项目的依赖包管理,最近看到基于Java17 的 Spring f ...
- 前端工程化与webpack的介绍
前端工程化 概念:在企业级的前端项目开发中,把前端开发所需的工具.技术.流程.经验等进行规范化.标准化. 模块化 js的模块化,css的模块化,资源的模块化 组件化 复用现有的UI结构,样式,行为 规 ...
- 【每日一题】【遍历orSet】2022年2月1日-NC66 两个链表的第一个公共结点
描述输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空.(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 输入描述:输入分为是3段,第 ...