Day 16 BBS项目01 表和注册功能
一、项目开发流程
1 互联网项目(产品经理提需求),传统行业项目(客户提需求)
2 项目开发流程
-需求分析(组长,项目经理,产品经理)
-原型设计(产品经理)
-美工UI切图
-设计程序,数据库(上面连个跟设计数据库可以同步操作)
-分任务开发(张三写用户相关,李四写订单相关),多人协同开发(git,svn)
-过了三个月所有任务开发完了
-测试(专门的测试)
-上线
3 项目开发模式
-瀑布模式: # 所有的做完了 才开始进行测试
-敏捷开发: # 做完一个小项目 就开始进行测试
4 博客项目需求
-多人博客
-博客首页
-登录:图片验证码
-注册:上传头像
-自己有自己的个人站点(根据分类,标签,时间,过滤文章)
-自己的后台管理
-发表博客(富文本编辑器,xss攻击处理)
-查看,删除
-文章分类
-随笔档案
-文章标签
-文章
-文章详情
-评论(根评论,子评论)
-点赞点踩
二、BBS项目表设计
此处省略,直接上代码 表与字段间的关系
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
# 1 用户信息
class User_info(AbstractUser):
phone = models.CharField(max_length=32) # 给默认表 添加一个字段
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png') # 继承的是char类 帮我们做了文件读写步骤
blog = models.OneToOneField(to='Blog', on_delete=models.CASCADE, null=True) # 在创建用户的时候 没有blog 所以要null
# 2 个人博客页面
class Blog(models.Model):
site_title = models.CharField(max_length=32)
site_name = models.CharField(max_length=32)
# 每个人的样式不同
site_style = models.CharField(max_length=32)
# 3 标签信息
class Tag(models.Model):
name = models.CharField(max_length=32)
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE, null=True)
# 4 分类信息
class Category(models.Model):
name = models.CharField(max_length=32)
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE, null=True)
# 5 文章信息
class Article(models.Model):
title = models.CharField(max_length=32)
introduction = models.CharField(max_length=254)
content = models.TextField()
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE)
tag = models.ManyToManyField(to='Tag')
category = models.ForeignKey(to='Category', on_delete=models.CASCADE)
# 6 评论表
class Commit(models.Model):
user = models.ForeignKey(to=User_info, on_delete=models.CASCADE)
article = models.ForeignKey(to=Article, on_delete=models.CASCADE)
create_time = models.DateTimeField(auto_now_add=True)
content = models.CharField(max_length=254)
# 7 点赞收藏表
class LikeAndCollect(models.Model):
user = models.ForeignKey(to=User_info, on_delete=models.CASCADE)
article = models.ForeignKey(to=Article, on_delete=models.CASCADE)
# 实质存的时候,是0和1
like = models.BooleanField()
collect = models.BooleanField()
create_time = models.DateTimeField(auto_now_add=True)
# 8 虚拟表 多对多关联
三、form组件编写
from django import forms
from django.core.exceptions import ValidationError
from django.forms import widgets
class SignUp(forms.Form):
username = forms.CharField(required=True, max_length=18, min_length=3,
error_messages={
'required': '该字段必须',
'max_length': '超过总长度',
'min_length': '密码长度不符合规范', })
password = forms.CharField(required=True, max_length=18, min_length=3, label='密码',
error_messages={'required': '该字段必填',
'max_length': '最大长度为18',
'min_length': '最短为3'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
re_password = forms.CharField(required=True, max_length=18, min_length=3, label='确认密码',
error_messages={'required': '该字段必填',
'max_length': '最大长度为18',
'min_length': '最短为3'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
def clean_username(self): # 局部钩子
username = self.cleaned_data.get('username') # type:str
if username.startswith('sb') or username.endswith('sb'):
raise ValidationError('账号含有敏感字符!')
else:
return username
def clean(self): # 全局钩子
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if password != re_password:
return ValidationError('两次密码不一致!')
return self.cleaned_data
四、注册页面搭建+头像实时显示
<style>
html body {
background-color: #f2f2f2;
}
</style>
<div class="container">
<div class="row">
<div class="col-md-4 offset-md-4" style="border: solid #dddddd;margin-top: 10%;background-color: white">
<form id="sign_form">
{% csrf_token %}
<div class="group" style="text-align: center">
<label for="avatar" id="avatar_label"
style="
color: #006edc">
<img src="https://gitee.com/A1L19/i-see-project/raw/master/Avatar/%E5%A4%B4%E5%83%8F%20(1).jpg"
style="width: 100px;height:100px;border-radius: 50%;
background-size: 100%;background-repeat: no-repeat;
background-color: #f2f2f2;" id="avatar_img">选择头像
</label>
<input type="file" id="avatar" style="display: none">
</div>
<div class="form-group">
<label for="exampleInputEmail1">用户名</label>
<input type="text" class="form-control" name="username">
<small id="emailHelp" class="form-text text-muted">请输入你的注册ID</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" name="password">
</div>
<div class="form-group">
<label for="exampleInputPassword1">RePassword</label>
<input type="text" class="form-control" name="re_password">
</div>
<div class="form-group" style="text-align: center">
<button type="button" class="btn btn-primary" id="submit">SignUp</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
$('#avatar').change(function () {
{#借助于文件阅读器#}
var filereader = new FileReader()
{#把图片读取到filereader中#}
{#读取文件#}
filereader.readAsDataURL($('#avatar')[0].files[0])
{#在读取文件时我们不能立马将文件写入到属性中,因为代码是立即执行的,写入时#}
{#可能还没有读取完成,所以我们要在读取完成后写入#}
filereader.onload = function () {
$('#avatar_img').attr('src', filereader.result)
}
})
</script>
</body>
五、注册功能完成
前端
{#提交文件#}
$('#submit').click(function () {
{## 创建一个表单对象#}
var formdata = new FormData()
formdata.append('avatar', $('#avatar')[0].files[0])
{#第一种方式逐个添加 太麻烦#}
{#第二种 基于循环添加#}
var sigle_data = $('#sign_form').serializeArray()
{#each 是 jquery提供的基于迭代的循环#}
$.each(sigle_data, function (k, v) {
formdata.append(v.name, v.value)
})
{#ajax提交数据#}
$.ajax({
url: '/signup/',
method: 'post',
processData: false,
contentType: false,
data: formdata,
success: function (res) {
if (res.code == 100) {
console.log(res.msg)
//js控制的跳转
location.href = res.url
} else {
alert(res['msg'])
}
}
})
})
后端
# settings
# 数据库配置 +
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
# 扩写auth_user表
AUTH_USER_MODEL = 'blog.user_info'
# views
def sign_up(request):
if request.method == 'POST':
res = {'code': 100, 'msg': '注册成功'}
form = SignUp(data=request.POST)
print(request.POST)
print(form.is_valid())
# 如果数据通过校验
if form.is_valid():
# 保存到数据库
data = form.cleaned_data
print(data)
# 我们要清除不要的数据 比如re_password
data.pop('re_password')
# 获取用户上传的头像文件
file = request.FILES.get('avatar')
# 如果存在自 给头像赋值
if file:
data['avatar'] = file
# 创建对象
models.User_info.objects.create_user(**data)
# 重定向地址
res['url'] = 'https://www.bilibili.com/'
return JsonResponse(res)
else:
res['code'] = 101 # 101表示注册失败
res['msg'] = '数据验证失败'
res['error'] = form.errors
return JsonResponse(res)
return render(request, 'signup.html')