-
登录功能(图片验证码)
-
注册功能(上传头像),基于forms
-
首页()
-
个人站点(个人样式不同,分类,标签,归档过滤)
-
文章内容
-
kafka:消息队列
-
rebbitmg(流量削峰)
-
-
点赞点彩
-
评论功能:公评论,子评论
-
后台管理
-
发布文章(富文本编辑器的使用,防止XSS攻击,XSS跨站脚本攻击,csrf跨站请求伪造)
2. 设计程序(数据库设计)
-
用户表
-
一对多的关系一旦确定,关联字段要写在多的一方
-
博客表(和用户表是一对一) -分类表:一对多 -跟标签:一对多
-
文章表 -跟用户表:一对多
-
分类表(和文章表一对多)
-
标签表(和文章表是多对多,一个文章对多个标签,一个标签对应多个文章)
-
点赞、点踩表 -跟用户表: 一对多 -跟文章表:一对多
-
评论表 -跟用户表:一对多 -跟文章表:一对多:一个文章中多个评论对应的是一个表中的多个数据
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)