BBS功能分析

1. 博客项目的需求分析(做什么功能)

  1. 登录功能(图片验证码)

  2. 注册功能(上传头像),基于forms

  3. 首页()

  4. 个人站点(个人样式不同,分类,标签,归档过滤)

  5. 文章内容

    1. kafka:消息队列

    2. rebbitmg(流量削峰)

  6. 点赞点彩

  7. 评论功能:公评论,子评论

  8. 后台管理

  9. 发布文章(富文本编辑器的使用,防止XSS攻击,XSS跨站脚本攻击,csrf跨站请求伪造)

2. 设计程序(数据库设计)

  1. 用户表

  2. 一对多的关系一旦确定,关联字段要写在多的一方

  3. 博客表(和用户表是一对一) -分类表:一对多 -跟标签:一对多

  4. 文章表 -跟用户表:一对多

  5. 分类表(和文章表一对多)

  6. 标签表(和文章表是多对多,一个文章对多个标签,一个标签对应多个文章)

  7. 点赞、点踩表 -跟用户表: 一对多 -跟文章表:一对多

  8. 评论表 -跟用户表:一对多 -跟文章表:一对多:一个文章中多个评论对应的是一个表中的多个数据

3. 数据迁移

4. 登录功能

知识点汇总:

__str__ 就是print
print就是调用里面的__str__方法


唯一联合:一个用户只能给一片文章点赞
unique_together = (('user','article'),)

设立图片的四种方式:

生成随机颜色
def get_random_color():
   return (random.randint(0,255),random.randint(0,255),random.randint(0,255))

方式一:返回固定图片
with open('static/img/code.png','rb') as f:
   data = f.read()
return Httpresponse(data)

方式二:自动生图片,需要借助第三方模块pillow 图像处理的模块
新生成一张图(保存在硬盘中)
img = Image.new('RGB',(350,40),get_random_color())
把图片保存起来
with open('static/img/code.png','wb') as f:
   img.save(f)
打开返回
with open('/static/img/','rb') as f:
   data = f.read()
return HttpResponse(data)

方式三:不把文件保存在硬盘中,保存在内存中
新生成一张图片
img = Image.new('RGB',(350,40),get_random_color())
生成Byteio对象
f = BytesIO()
把文件保存到对象中
img.save(f,'png')
把文件从对象中取出来
f.getvalue()
return HttpResponse(f.getvalue())

方法四:在图片上写文件,并保存到内存中
img = Image.new('RGB',(350,40),get_rnadom_color())
写文字,生成一个字体对象
font = ImageFont.truetype('/static/font/kumo.ttf',34)
调用方法 返回一个画板对象
draw = ImageDraw.Draw(img)
draw.text((0,10),'python',font=font)

f = BytesIO()
img.save(f,'png')
return HttpResponse(f.getvalue())

动态生成大写小写数字5个

for i in range(5):
   num = str(random.randint(0,9))
   up_chr=str(chr(random.randint(65,90)))
   lower_chr = str(chr(random.randint(97,122)))
从三个字符任选
ss = random.choice([num,up_chr,lower_chr])
draw.text((20+i*50,5),ss,font=font,fill=get_random_color())

画点和线


画点和线
   width = 320
   height = 35
   for i in range(10):
       x1 = random.randint(0, width)
       x2 = random.randint(0, width)
       y1 = random.randint(0, height)
       y2 = random.randint(0, height)
       # 在图片上画线
       draw.line((x1, y1, x2, y2), fill=get_random_color())
       
   for i in range(100):
       # 画点
       draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
       x = random.randint(0, width)
   #   y = random.randint(0, height)
   # 画弧形
   draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())

建表:

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
   nid = models.AutoField(primary_key=True)
   # 头像:FileField文件(varchar类型),default:默认值,upload_to上传的路径
   avatar = models.FileField(upload_to='avatar/', default='avatar/default.png')
   #跟blog表一对一
   #OneToOneField本质就是ForeignKey,只不过有个唯一性约束
   blog = models.OneToOneField(to='Blog', to_field='nid',null=True)
   # blog = models.ForeignKey(to='Blog', to_field='nid',null=True,unique=True)

   class Meta:
       # db_table='xxxx'
       # 在admin中显示的表名
       verbose_name='用户表'
       #去掉 用户表 后的s
       verbose_name_plural = verbose_name

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)
   def __str__(self):
       return self.site_name
#分类表
class Category(models.Model):
   nid = models.AutoField(primary_key=True)
   #分类名称
   title = models.CharField(max_length=64)
   #跟博客是一对多的关系,关联字段写在多的一方
   #to 是跟哪个表关联   to_field跟表中的哪个字段做关联, null=True 表示可以为空
   blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
   def __str__(self):
       return self.title

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)
   def __str__(self):
       return self.title

class Article(models.Model):
   nid = models.AutoField(primary_key=True)
   #verbose_name在admin中显示该字段的中文
   title = models.CharField(max_length=64,verbose_name='文章标题')
   #文章摘要
   desc = models.CharField(max_length=255)
   #文章内容 大文本
   content = models.TextField()
   #DateTimeField 年月日时分秒(注意跟datafield的区别)
   #auto_now_add=True:插入数据会存入当前时间
   #auto_now=True 修改数据会存入当前时间
   create_time = models.DateTimeField(auto_now_add=True)
   # commit_num=models.IntegerField(default=0)
   # up_num=models.IntegerField(default=0)
   # down_num=models.IntegerField(default=0)
#一对多的关系
   blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
   # 一对多的关系
   category = models.ForeignKey(to='Category', to_field='nid', null=True)
   #多对多关系 through_fields 不能写反了:
   tag = models.ManyToManyField(to='Tag', through='ArticleTOTag', through_fields=('article', 'tag'))
   def __str__(self):
       return self.title+'----'+self.blog.userinfo.username

class ArticleTOTag(models.Model):
   nid = models.AutoField(primary_key=True)
   article = models.ForeignKey(to='Article', to_field='nid')
   tag = models.ForeignKey(to='Tag', to_field='nid')

class Commit(models.Model):
   #谁对那篇文章评论了什么内容
   nid = models.AutoField(primary_key=True)
   user = models.ForeignKey(to='UserInfo', to_field='nid')
   article = models.ForeignKey(to='Article', to_field='nid')
   content = models.CharField(max_length=255)
   #评论时间
   create_time = models.DateTimeField(auto_now_add=True)
   #自关联()评论下面也可能会有子评论,所以要子关联
   parent = models.ForeignKey(to='self', to_field='nid',null=True,blank=True)

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')
   #布尔类型,本质也还是0和1
   is_up = models.BooleanField()

   class Meta:
       #联合唯一,一个用户只能给一片文章点赞或点踩
       unique_together = (('user', 'article'),)

登录界面

views.py


from django.shortcuts import render,HttpResponse,redirect
from django.http import JsonResponse
#Image导入
#ImageDraw在图片上写字
#ImageFont 写字的格式
from PIL import Image,ImageDraw,ImageFont
import random
# 相当于把文件以byte格式存到内存中
from io import BytesIO
# Create your views here.
def login(request):
   if request.method=='GET':
       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('static/img/code.png','rb') as f:
   #     data=f.read()
   # return HttpResponse(data)
   #方式二,自动生成图片(需要借助第三方模块pillow)图像处理的模块
   #新生成一张图片
   # img=Image.new('RGB',(350,40),get_random_color())
   # #把图片保存起来
   # with open('static/img/code.png','wb') as f:
   #     #把图片保存起来(注意,用img对象的save方法,把f传入)
   #     img.save(f)
   # #打开返回
   # with open('static/img/code.png','rb') as f:
   #     data=f.read()
   # return HttpResponse(data)
   #方式三(不把文件保存在硬盘上,保存在内存中)
   #新生成一张图片
   # img=Image.new('RGB',(350,40),get_random_color())
   # #生成一个Byteio对象
   # f=BytesIO()
   # #把文件保存到对象中
   # img.save(f,'png')
   # #f.getvalue() 把文件从对象中取出来
   # return HttpResponse(f.getvalue())
   #方式四:在图片上写文件,并且保存到内存中
   # img = Image.new('RGB', (350, 40), get_random_color())
   # #写文字
   # #生成一个字体对象
   # font=ImageFont.truetype('static/font/kumo.ttf',34)
   # #调用方法,返回一个画板对象
   # draw=ImageDraw.Draw(img)
   # draw.text((0,10),'python',font=font)
   #
   # f=BytesIO()
   # img.save(f,'png')
   # return HttpResponse(f.getvalue())

   #最终版本
   img = Image.new('RGB', (350, 40), get_random_color())
   font=ImageFont.truetype('static/font/kumo.ttf',34)
   draw=ImageDraw.Draw(img)
   #动态生成大写,小写,数字 5个
   # draw.text((0,10),'python',font=font)
   for i in range(5):
       num=str(random.randint(0,9))
       up_chr=str(chr(random.randint(65,90)))
       lower_chr=str(chr(random.randint(97,122)))
       #从三个字符中选一个字符
       ss=random.choice([num,up_chr,lower_chr])
       draw.text((20+i*50, 5), ss, font=font,fill=get_random_color())
   #画点和线
   # width = 320
   # height = 35
   # for i in range(10):
   #     x1 = random.randint(0, width)
   #     x2 = random.randint(0, width)
   #     y1 = random.randint(0, height)
   #     y2 = random.randint(0, height)
   #     # 在图片上画线
   #     draw.line((x1, y1, x2, y2), fill=get_random_color())
   #
   # for i in range(100):
   #     # 画点
   #     draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
   #     x = random.randint(0, width)
   #     y = random.randint(0, height)
   #     # 画弧形
   #     draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
   f=BytesIO()
   img.save(f,'png')
   return HttpResponse(f.getvalue())
posted @ 2019-09-02 09:51  蜗牛少少  阅读(291)  评论(0编辑  收藏  举报