一、项目简介
制作类似博客园网站(https://www.cnblogs.com/)的基本功能
二、需求分析
- 登陆功能 (基于Ajax,图片验证码)
- 注册功能 (基于Ajax,基于forms验证)
- 博客首页
- 个人站点
- 文章详情
- 点赞,点踩
- 评论
——根评论
——子评论 - 后台管理
——文章展示 - 发布文章
——富文本编辑器
——防止xss攻击
建表:
UserInfo(AbstractUser) 用户表
Blog 站点表
Category 分类表
Tag 标签表
Article2Tag 中间表
Article 文章表
ArticleUpDown 文章顶踩表
Comment 评论表
- UserInfo(AbstractUser)
nid
telephone
avatar
create_date
blog 用户博客——一对一对应博客表 - Blog
nid
title
site_name
theme - Tag
nid
title
blog - Article
nid
title
desc
content
create_date
user
user:跟user一对多关系
文章作者
category
category:眼Category一对多
文章分类
tag
tag:跟Tag多对多
文章标题(通过through指定自己写的中间表) - Article2Tag
nid
article
tag - ArticleUpDown
nid
user
article
is_up 赞还是踩 - Comment
nid
user
article
comm
create_date
parent_comment
BBS关系表图:
settings.py
# 继承新模块时需要指定其模块路径 AUTH_USER_MODEL='mybbs.UserInfo'
# 添加static路径 STATICFILES_DIRS=[ os.path.join(BASE_DIR,'static') ]
models.py
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
# 继承AbstractUser表,应用auth模块
class UserInfo(AbstractUser):
nid = models.AutoField(primary_key=True)
# 手机号
telephone = models.CharField(max_length=32)
# 用户头像
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png')
# 用户创建时间
create_date = models.DateTimeField(auto_now_add=True)
# 用户博客--一对一对应博客表
blog = models.OneToOneField(to="Blog", to_field='nid', on_delete=models.CASCADE, null=True)
class Blog(models.Model):
nid = models.AutoField(primary_key=True)
# 博客名称
title = models.CharField(max_length=32)
# 站点名称
site_name = models.CharField(max_length=32)
# 博客主题样式
theme = models.CharField(max_length=32)
class Category(models.Model):
nid = models.AutoField(primary_key=True)
# 分类名称
title = models.CharField(max_length=32)
# 所属博客
blog = models.ForeignKey(to="Blog", to_field='nid', on_delete=models.CASCADE, null=True)
class Tag(models.Model):
nid = models.AutoField(primary_key=True)
# 标签名称
title = models.CharField(max_length=32)
# 所属博客
blog = models.ForeignKey(to="Blog", to_field='nid', on_delete=models.CASCADE, null=True)
class Article(models.Model):
nid = models.AutoField(primary_key=True)
# 文章标题
title = models.CharField(max_length=32)
# 文章摘要
desc = models.CharField(max_length=255)
# 存大文本
# 文章内容
content = models.TextField()
# 创建时间
create_date = models.DateTimeField(auto_now_add=True)
# user:跟user一对多
# 文章作者
user = models.ForeignKey(to='UserInfo', to_field='nid', null=True)
# category: 跟Category一对多
# 文章分类
category = models.ForeignKey(to='Category', to_field='nid', null=True)
# tag:跟Tag多对多
# 文章标题(通过through指定自己写的中间表)
tag = models.ManyToManyField(to='Tag', through='Article2Tag', through_fields=('article', 'tag'))
class Article2Tag(models.Model):
nid = models.AutoField(primary_key=True)
# 文章id
article = models.ForeignKey(to='Article', to_field='nid', null=True)
# 标签id
tag = models.ForeignKey(to='Tag', to_field='nid', null=True)
class ArticleUpDown(models.Model):
nid = models.AutoField(primary_key=True)
# 点赞/点踩 的用户
user = models.ForeignKey(to='UserInfo', to_field='nid')
# 点赞/点踩 的文章
article = models.ForeignKey(to='Article', to_field='nid', null=True)
# 赞还是踩
is_up = models.BooleanField(default=True)
class Comment(models.Model):
nid = models.AutoField(primary_key=True)
# 评论的用户
user = models.ForeignKey(to='UserInfo', to_field='nid')
# 评论的文章
article = models.ForeignKey(to='Article', to_field='nid')
# 评论的内容
comm = models.CharField(max_length=255)
# 评论的id
create_date = models.DateTimeField(auto_now_add=True)
# parent_comment=models.ForeignKey(to='Comment',to_field='nid')
# 父评论的id,自关联,防止写脏数据
parent_comment = models.ForeignKey(to='self', to_field='nid', null=True)
urls.py
# 导入views模块 from mybbs import views
# 开启路径地址 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/$', views.login), url(r'^get_code/$', views.get_code), ]
views.py
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
import random
# pip3 install pillow
from PIL import Image,ImageDraw,ImageFont
# 内存管理,把图片放在内存里
from io import BytesIO
from django.contrib import auth
# Create your views here.
def login(request):
#判断前台是否是ajax发过来的数据
if request.is_ajax():
back_msg={'user':None,'msg':None}
name=request.POST.get('name')
pwd=request.POST.get('pwd')
valid_code=request.POST.get('valid_code')
print(name,pwd,valid_code)
if valid_code.upper()==request.session.get('valid_code').upper():
user= auth.authenticate(request,username=name,password=pwd)
if user:
auth.login(request,user)
back_msg['user']=name
back_msg['msg']='登陆成功'
else:
back_msg['msg']='用户名或密码错误'
else:
back_msg['msg'] = '验证码错误'
return JsonResponse(back_msg)
return render(request,'login.html')
def get_random_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
def get_code(request):
# 方式一
# with open('lhf.jpg','rb') as f:
# data=f.read()
# 方式2
# img=Image.new('RGB',(300,35),color='pink')
#
# with open('code.png','wb') as f:
# img.save(f,'png')
# with open('code.png','rb') as f:
# data=f.read()
img = Image.new('RGB', (300, 35), color=get_random_color())
# 指定字体文件
font=ImageFont.truetype('static/font/kumo.ttf',30)
draw=ImageDraw.Draw(img)
valid_code=''
for i in range(5):
random_num=str(random.randint(0,9))
random_upper=chr(random.randint(65,90))
random_lower=chr(random.randint(97,122))
random_chr=random.choice([random_num,random_upper,random_lower])
draw.text((i*40+50, 3), random_chr, get_random_color(), font=font)
valid_code+=random_chr
# draw.text((5,5),'python',get_random_color(),font=font)
print(valid_code)
request.session['valid_code']=valid_code
# 生成一个内存管理的对象
f=BytesIO()
# 把图片保存到内存中
img.save(f, 'png')
# 从内存中取出来
data=f.getvalue()
return HttpResponse(data)
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/bootstrap-3.3.7-dist/css/bootstrap.min.css">
<script src="/static/jquery-3.3.1.js"></script>
<title>登录页面</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>登录页面</h1>
{% csrf_token %}
<div class="form-group">
<label for="id_name">用户名</label>
<input type="text" id="id_name" class="form-control">
</div>
<div class="form-group">
<label for="id_pwd">密码</label>
<input type="password" id="id_pwd" class="form-control">
</div>
<div class="form-group">
<label for="valid_code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" id="valid_code" class="form-control">
</div>
<div class="col-md-6">
<img height="35" width="300" src="/get_code/" alt="" id="cod_img">
{# <img height="35" width="250" src="/static/img/lhf.jpg" alt="">#}
</div>
</div>
</div>
<div>
<button class="btn btn-danger" id="submit_btn">提交</button><span class="error"></span>
</div>
</div>
</div>
</div>
<script>
$("#cod_img").click(function () {
$("#cod_img")[0].src = $("#cod_img")[0].src + "?"
})
$("#submit_btn").click(function () {
$.ajax({
url: '',
type: 'post',
data: {
'name': $("#id_name").val(),
'pwd': $("#id_pwd").val(),
'valid_code': $("#valid_code").val(),
'csrfmiddlewaretoken': "{{ csrf_token }}"
},
success: function (data) {
if (data.user){
alert(data.msg)
}else {
$(".error").text(data.msg)
setTimeout(function () {
$(".error").text("")
},1000)
}
}
})
})
</script>
</body>
</html>