云笔记项目
文章目录

一般项目组成成员
- 产品/运营经理 : 负责产品功能细节的把控
- 开发
- 前端 - 负责显示部分内容的开发 [多]
- 后端 - 负责服务器部分的功能开发 [少]
- 运维 - 管理 linux 服务器,组件化配置,安全问题
- 测试 - 负责找出产品功能的问题[bug]
- 美工 - 负责产品素材方面的绘制
功能拆解
一般情况下由产品经理负责
- 用户模块
- 注册 - 成为用户平台
- 登陆 - 校验用户身法
- 退出登陆 - 退出登陆状态
- 笔记模块
- 查看笔记列表 - 查
- 创建新笔记 - 增
- 修改笔记 -该
- 删除笔记 -删
初始化项目
创建一个 tedu_note
项目,然后初始化下列配置
django-admin startproject tedu_note
- 禁止csrf
- 语言更改
- 时区更改
- 数据库配置
- 创建/注册应用 user
用户模型类设计
创建我们的 User 模型类
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField("用户名",max_length=30,unique=True)
password = models.CharField("密码",max_length=32)
# 下面这两条网站都是每个模型必须要给的
create_time = models.DateTimeField("创建时间",auto_now_add=True) # 只有当我们第一次更新的时候才会写入
update_time = models.DateTimeField("更新时间",auto_now=True) # 每一次更新都会重置时间
def __str__(self):
return f'{self.username} - {self.create_time} - {self.update_time}'
用户注册 第一版
- url :
/user/reg
- 视图函数: reg_view
- 模板位置:
templates/user/register.html
- 界面样式
- 书写
register.html
内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form method="post" action="/user/reg">
<p>用户名 <input type="text" name="username"></p>
<p>密码 <input type="text" name="password"></p>
<p>重复你的密码 <input type="text" name="password2"></p>
<button type="submit" value="reg">注册</button>
</form>
</body>
</html>
- 写视图文件
from django.http import HttpResponse
from django.shortcuts import render
from .models import User
# Create your views here.
def reg_view(request):
if request.method == "GET":
return render(request, 'user/register.html')
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
# 检测是否为空
if username == '' or password == '':
return HttpResponse("账户名或者密码不能为空!")
# 检测两次密码是否一致
if password != password2:
return HttpResponse("两次密码输入不一致")
# 检测用户名是否可用
old_user = User.objects.filter(username=username)
if old_user:
return HttpResponse(f"当前账户名 {username} 已经有人注册")
# 如果都没出错就插入数据
User.objects.create(username=username,password=password)
return HttpResponse("注册成功!")
- 写 url.py 路由文件
# 主 urls.py 内容
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('user/',include("user.urls"))
]
# 子 urls.py 内容
from django.urls import path
from . import views
urlpatterns = [
path('reg', views.reg_view)
]
- 查看我们的页面
用户注册 第二版
我们现在新增了 3 个需求
- 密码能够密文化,防止数据库泄露
- 插入问题[高并发的时候]
- 要求注册后就免登录一天
要求 1 密码问题
我们可以使用 哈希算法,给明文然后计算出一段定长的不可逆的值(md5, sha-256)
- 哈希算法特点
- 定长输出:不管明文输入长度为多少,哈希值都是定长的,md5 - 32为16进制
- 不可逆:无法反向计算出对应的明文
- 雪崩效应:输入只要发出一点改变,输出发生大变化
- 常用使用场景
- 密码保存
- 网络传递文件的时候文件校对
如何在 python 中使用哈希算法
import hashlib
# 选择使用的哈希算法
m = hashlib.md5()
# 输入我们的值(注意需要在前面加上 b 前缀,因为我们输入的需要是一个字节码)
m.update(b'13829242002')
# 获取我们的16进制摘要
m.hexdigest()
我们现在就可以开始修改我们的密码保存,来让我们能够存入一个密文的密码
def reg_view(request):
if request.method == "GET":
return render(request, 'user/register.html')
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
# 检测是否为空
if username == '' or password == '':
return HttpResponse("账户名或者密码不能为空!")
# 检测两次密码是否一致
if password != password2:
return HttpResponse("两次密码输入不一致")
# 检测用户名是否可用
old_user = User.objects.filter(username=username)
if old_user:
return HttpResponse(f"当前账户名 {username} 已经有人注册")
# 插入前对密码进行密文的处理
m = hashlib.md5()
m.update(password.encode())
password_m = m.hexdigest()
# 如果都没出错就插入数据
User.objects.create(username=username,password=password_m)
return HttpResponse("注册成功!")
要求2 高并发问题
我们在正式的环境中,因为有多个人可能会同时访问我们的数据库,所有唯一索引有可能会报错,我们现在需要使用 try 语句来防止我们的程序报错
- 原来
# 如果都没出错就插入数据
User.objects.create(username=username,password=password_m)
return HttpResponse("注册成功!")
- 修改后
# 如果都没出错就插入数据
try:
User.objects.create(username=username,password=password_m)
return HttpResponse("注册成功!")
except Exception as e:
print(e)
return HttpResponse("当前用户名已经被注册!")
要求3 注册免登录一天
# 免登陆一天
request.session['username'] = username
request.session['uuid'] = user.id
我们的 是否记住我
勾选之后我们的提交请求就会多出来一项remember=on
,我们只需要判断我们的 request.POST 中有没有这个键即可
- 判断勾选了记住我,我们给用户一个 cookies
# 如果用户点击长时间记住我(保存3天)
resp = HttpResponse("登陆成功!")
if 'remember' in request.POST:
resp.set_cookie('username',username,3600*24*3)
resp.set_cookie('uuid',user.id, 3600*24*3)
return resp
用户登陆
用户进入登陆页面的时候判断是否在cookies有效期内
- 原代码
if request.method == "GET":
return render(request,'user/login.html')
- 修改后
if request.method == "GET":
# 检查 session
if request.session.get('username') and request.session.get('uuid'):
return HttpResponse("已登陆,即将返回主页")
# 检查 cookies
c_username = request.COOKIES.get('username')
c_uuid = request.POST.get('c_uuid')
if c_uuid and c_username:
# 重新写入新的 session 到我们的数据库
request.session['username'] = c_username
request.session['uuid'] = c_uuid
return HttpResponse("已登陆,即将返回主页")
return render(request,'user/login.html')
网站首页
我们直接使用模板来判断页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{% if request.session.username %}
<p> 欢迎 {{request.session.username}} </p>
{% else %}
{% if request.cookie.username %}
<p> 欢迎 {{request.cookie.username}}</p>
{% else %}
<p><a href="/user/login">登陆</a></p>
<p><a href="/user/reg">注册</a></p>
{% endif %}}
{% endif %}
</body>
</html>
退出登陆
- 视图修改
def logout_view(request):
# 清除我们的 session 和 cookie 并且返回登陆页面
del request.session['username']
del request.session['uuid']
response = HttpResponseRedirect(reverse('home'))
response.delete_cookie('username')
response.delete_cookie('uuid')
return response
- 修改一下HTML
- 查看网页
笔记模型类
class Note(models.Model):
title = models.CharField("标题",max_length=100)
content = models.TextField("内容")
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
这个练习与之前的练习冲突,请前往查看图书管理练习