一般项目分为5个步骤:
1.需求分析
2.设计程序以及程序的架构
3.分任务开发程序
4.测试
5.上线
评论
? 一个用户对应一个站点所以用户表和个人站点表属于一对一,个人站点表与文章表,分类表,标签表都属于一对多,一个分类有多篇文章,所以分类表对于文章表属于一对多,标签表对于文章表是属于多对多,文章表对于评论表,点赞点踩表属于一对多,评论表可以有根评论和子评论,可以自关联。
# 用户表
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'),)
1.可以使用自带sqlite
2.使用mysql
# setting.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bbs',
'HOST':'127.0.0.1',
'USER':'root',
'PASSWORD':'123',
'PORT':3306
}
}
#使用auth认证自定义的用户表
AUTH_USER_MODEL = "blog.UserInfo"
# __init__.py
import pymysql
pymysql.install_as_MySQLdb()
python manage.py makemigrations
python manage.py migrate
#login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登陆</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1>登陆</h1>
<form action="">
<div class="form-group">
<label for="id_name">用户名</label>
<input type="text" name="name" id="id_name" class="form-control">
</div>
<div class="form-group">
<label for="id_pwd">密码</label>
<input type="password" name="pwd" id="id_pwd" class="form-control">
</div>
<div class="form-group">
<label for="id_code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" name="code" id="id_code" class="form-control">
</div>
<div class="col-md-6">
<img src="/get_code/" height="40" width="350">
</div>
</div>
</div>
<input type="submit" value="提交" class="btn-success">
</form>
</div>
</div>
</div>
</body>
</html>
# 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())
原文:https://www.cnblogs.com/yellowcloud/p/11385545.html