标签:btn middle $.ajax alert art 继承 sql 文本编辑 http
项目流程:
1 搞清楚需求(产品经理)
(1) 基于用户认证组件和Ajax实现登录验证(图片验证码)
(2) 基于forms组件和Ajax实现注册功能
(3) 设计系统首页(文章列表渲染)
(4) 设计个人站点页面---跨表查询,分组查询
(5) 文章详情页
(6) 实现文章点赞功能
(7) 实现文章的评论
---文章的评论
---评论的评论
(8) 副文本编辑框 和 防止xss攻击(防止别人提交js代码)
2 设计表结构
3 按着每一个功能分别进行开发
4 功能测试
5 项目部署上线
用户表:UserInfo
个人站点表:blog
文章表:Article
评论表:commit
点赞点踩表:upanddown
文章分类表:category
文章标签表:tag
User:继承AbstractUser,用户表
nid
phone
avatar 用户头像
blog
Blog:站点
nid
title
site_name
theme
category:分类
nid
title
blog 跟blog一对多
tag:(文章关键字)
nid
title
blog 跟blog一对多
article:文章
nid
title
desc 摘要
create_time auto_add_now:当该条记录创建时,自动添加当前时间
content 文章内容
category 一对多
blog 一对多
tag 多对多
commit:评论
nid
user 哪个用户
article 对哪篇文章
content 评论了什么内容
commit_time 时间
parent_id 子评论
UpAndDown:点赞
nid
user
article
is_up
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserInfo(AbstractUser):
nid = models.AutoField(primary_key=True)
# 电话可以为空
phone = models.CharField(max_length=32, null=True)
# 头像
avatar = models.FileField(upload_to=‘avatar/‘, default=‘/static/image/default.png‘)
# 站点
blog = models.OneToOneField(to=‘Blog‘, to_field=‘nid‘)
# 用户和用户的站点应该是联合唯一的
class Mate:
unique_together = ((‘username‘, ‘blog‘),)
class Blog(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=64)
# 站点路径
site_name = models.CharField(max_length=32)
# 主题
theme = models.CharField(max_length=64)
# 分类
class Category(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=64)
# 个人站点可以拥有多个分类
blog = models.ForeignKey(to=‘Blog‘, to_field=‘nid‘, null=True)
# 标签
class Tag(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=64)
# 个人站点可以拥有多个标签
blog = models.ForeignKey(to=‘Blog‘, to_field=‘nid‘, null=True)
# 文章
class Article(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=64)
# 文章简介
desc = models.CharField(max_length=255)
# 文章内容
content = models.TextField()
# 创建时间
create_time = models.DateTimeField(auto_now_add=True)
# 个人站点可以拥有多篇文章
blog = models.ForeignKey(to=‘Blog‘, to_field=‘nid‘, null=True)
# 一个分类可以拥有多篇文章
category = models.ForeignKey(to=‘Category‘, to_field=‘nid‘, null=True)
# 文章和标签是多对多的关系,一篇文章可以由多个标签,一个标签可以给多篇文章使用
# 手动创建第三张表
tag = models.ManyToManyField(to=‘Tag‘, through=‘Article2Tag‘, through_fields=(‘article‘, ‘tag‘))
# 多对多第三张表
class Article2Tag(models.Model):
nid = models.AutoField(primary_key=True)
tag = models.ForeignKey(to=‘Tag‘, to_field=‘nid‘)
article = models.ForeignKey(to=‘Article‘, to_field=‘nid‘)
class Mate:
unique_together = ((‘tag‘, ‘article‘),)
# 评论
class Commit(models.Model):
nid = models.AutoField(primary_key=True)
# 评论内容
content = models.TextField()
# 评论时间
create_time = models.DateTimeField(auto_now_add=True)
# 可以对评论作出评论,设置一个字段用来表示是对哪条评论做出的评论
# 方法1
# parent_id = models.ForeignKey(to=‘Commit‘,to_field=‘nid‘)
# 方法2
parent_id = models.ForeignKey(to=‘self‘,to_field=‘nid‘)
# 一个用户可以评论多条
user = models.ForeignKey(to=‘UserInfo‘, to_field=‘nid‘)
# 一篇文章可以有多条评论
article = models.ForeignKey(to=‘Article‘, to_field=‘nid‘)
# 点赞
class UpAndDown(models.Model):
nid = models.AutoField(primary_key=True)
# 一个用户可以给多篇文章点赞或踩一下
user = models.ForeignKey(to=‘UserInfo‘, to_field=‘nid‘)
# 一篇文章可以有多个赞和踩
article = models.ForeignKey(to=‘Article‘, to_field=‘nid‘)
# 1是赞,0是踩
is_up = models.BooleanField()
class Meta:
# 一个用户只能对一篇文章赞或踩,所以要做联合唯一
unique_together = ((‘user‘, ‘article‘),)
#链接数据库
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.mysql‘,
‘NAME‘: ‘bbs‘,
‘POST‘: 3306,
‘HOST‘: ‘127.0.0.1‘,
‘USER‘: ‘root‘,
‘PASSWORD‘: ‘root‘
}
}
#静态文件路径配置
STATICFILES_DIRS = [
os.path.join(BASE_DIR, ‘static‘)
]
#auth组件authinfo表路径
AUTH_USER_MODEL = ‘blog.UserInfo‘
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
{% load static %}
<link rel="stylesheet" href="{% get_static_prefix %}bootstrap-3.3.7-dist/css/bootstrap.css">
<script src="{% get_static_prefix %}jquery-3.3.1.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<h1 style="text-align: center">登录</h1>
<form>
{% csrf_token %}
<div class="form-group">
<label for="name">用户名</label>
<input type="text" class="form-control" id="name" placeholder="用户名" required>
</div>
<div class="form-group">
<label for="pwd">密码</label>
<input type="password" class="form-control" id="pwd" placeholder="密码" required>
</div>
<div class="form-group">
<label for="validCode">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="validCode" placeholder="验证码不分大小写" required>
</div>
<div class="col-md-6">
<img src="/get_validCode/" title="60s后失效" height="35" width="200" class="img-rounded"
id="get_validCode_img">
</div>
</div>
</div>
</form>
<button type="button" class="btn btn-primary btn-lg pull-right" id="btn">登录</button>
</div>
</div>
</div>
</body>
<script>
$(function () {
$("#get_validCode_img").click(function () {
$(this)[0].src += ‘?‘
})
});
$(‘#btn‘).click(function () {
var da = {‘name‘:$(‘#name‘).val(),‘pwd‘:$(‘#pwd‘).val(),‘validCode‘:$(‘#validCode‘).val(),csrfmiddlewaretoken:$("[name=‘csrfmiddlewaretoken‘]").val()}
$.ajax({
url:‘/login/‘,
type:‘post‘,
data:da,
success:function (data) {
alert(data)
}
})
})
</script>
</html>
验证码
from PIL import Image, ImageDraw, ImageFont
from BBS import common
from io import BytesIO
def get_validCode(request):
# 第一种方式:本地存放固定图片
# with open(‘static/1.png‘,‘rb‘) as f:
# data = f.read()
# return HttpResponse(data)
# # 第二种方式:本地存放随机图片
# # 生成图片 new(模式,宽高,颜色)
# img = Image.new(‘RGB‘, (200, 35),color=common.get_color())
# # 写一个空白本地图片文件
# with open(‘ve_code.png‘, ‘wb‘) as f:
# # 调用img对象的save方法保存到空文件
# img.save(f,‘png‘)
# # 打开文件,再返回
# with open(‘ve_code.png‘,‘rb‘) as f:
# data = f.read()
# return HttpResponse(data)
# # 第三种方式:在内存中存放随机图片
# # 生成图片 new(模式,宽高,颜色)
# img = Image.new(‘RGB‘, (200, 35),color=common.get_color())
# # 生成一个空白内存文件
# f = BytesIO()
# # 调用img对象的save方法保存到空内存文件
# img.save(f,‘png‘)
# # 获取内存文件的内容
# data = f.getvalue()
# return HttpResponse(data)
# 第四种方式:在内存中存放随机图片,在图片上加上随机验证码
# 生成图片对象 new(模式,宽高,颜色)
img = Image.new(‘RGB‘, (200, 35), color=common.get_color())
# 生成画笔对象,并将图片对象传入
img_draw = ImageDraw.Draw(img)
# 生成字体对象
font = ImageFont.truetype(‘static/font/ss.ttf‘, size=25)
# 将文字用画笔写入图片
# text(坐标,文字,颜色,字体)
img_draw.text((50, 0), common.get_ve_code(request), common.get_color(), font)
# 生成一个空白内存文件
f = BytesIO()
img.save(f, ‘png‘)
data = f.getvalue()
return HttpResponse(data)
共用模块
import random
# 产生随机RGB
def get_color():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
# 产生随机验证码
def get_ve_code(request):
ve_code = ‘‘
for i in range(5):
number = random.randint(0, 9)
upper = chr(random.randint(97, 122))
lower = chr(random.randint(65, 90))
add = random.choice((number, upper, lower))
ve_code += str(add)
request.session[‘ve_code‘]=ve_code
request.session.set_expiry(60)
return ve_code
登录
from django.shortcuts import render, HttpResponse
from django.contrib import auth
# Create your views here.
def login(request):
if request.method == ‘GET‘:
return render(request, ‘login.html‘)
else:
name = request.POST.get(‘name‘)
pwd = request.POST.get(‘pwd‘)
validCode = request.POST.get(‘validCode‘)
user = auth.authenticate(username=name, password=pwd)
validCode_sess = request.session.get(‘ve_code‘)
if validCode.upper() != validCode_sess.upper():
return HttpResponse(‘验证码错误‘)
if user is not None:
return HttpResponse(‘登陆成功‘)
else:
return HttpResponse(‘用户名或密码错误‘)
标签:btn middle $.ajax alert art 继承 sql 文本编辑 http
原文地址:https://www.cnblogs.com/xvchengqi/p/10028392.html