Python學習之路—2018/7/10
阿新 • • 發佈:2018-07-11
ike tro 頁面 django trac link point img head
Python學習之路—2018/7/10
博客開發項目流程
? 一般來說,一個項目的開發流程分為:項目需求、設計表結構、功能開發、測試功能、產品上線,本次學習以博客園為藍本進行開發。
1.項目需求
博客的開發的需求主要有以下幾點:
- 基於auth模塊和Ajax實現登錄驗證
- 基於forms組件和Ajax實現註冊功能
- 設計博客首頁
- 設計個人站點頁面
- 設計文章詳情頁面
- 實現文章點贊功能
- 實現文章的評論功能,包括對文章的評論以及對文章評論的評論
- 實現富文本編輯框
- 防止xss攻擊(例如當用戶的文章中含有JS代碼,其他用戶進行訪問時瀏覽器會執行JS代碼,大大降低了用戶的安全性)
2.設計表結構
根據功能分析主要有用戶信息表(User)、博客信息表(Blog)、博客文章分類信息表(Sort)、博客文章標簽信息表(Tag)、博客文章表(Article)、文章點贊表(Like)、文章評論表(Comment),它們之間的關系如下圖所示:
models.py
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): """ 用戶信息表 """ uid = models.AutoField(primary_key=True) phone = models.CharField(max_length=11, unique=True, null=True) avatar = models.FileField(upload_to="avatars/", default="/avatars/default.jpg") create_time = models.DateField(verbose_name="創建日期", auto_now_add=True) blog = models.OneToOneField(to="Blog", to_field="bid", null=True, on_delete=models.CASCADE) # 與博客建立一對一關系 def __str__(self): return self.username class Blog(models.Model): """ 博客信息表 """ bid = models.AutoField(primary_key=True) title = models.CharField(max_length=32, verbose_name="個人博客標題") theme = models.CharField(max_length=32, verbose_name="博客主題") site = models.CharField(max_length=32, verbose_name="個人站點名稱") def __str__(self): return self.site class Sort(models.Model): """ 博客文章分類信息表 """ sid = models.AutoField(primary_key=True) title = models.CharField(max_length=32, verbose_name="分類標題") blog = models.ForeignKey(to="Blog", to_field="bid", on_delete=models.CASCADE) # 與博客建立一對多關系 def __str__(self): return self.title class Tag(models.Model): """ 博客文章標簽信息表 """ tid = models.AutoField(primary_key=True) name = models.CharField(max_length=32, verbose_name="標簽名稱") blog = models.ForeignKey(to="Blog", to_field="bid", on_delete=models.CASCADE) # 與博客建立一對多關系 def __str__(self): return self.name class Article(models.Model): """ 博客文章表 """ aid = models.AutoField(primary_key=True) title = models.CharField(max_length=32, verbose_name="文章標題") abstract = models.CharField(max_length=32, verbose_name="文章摘要") create_time = models.DateField(verbose_name="創建日期", auto_now_add=True) content = models.TextField() user = models.ForeignKey(to="User", to_field="uid", verbose_name="作者", on_delete=models.CASCADE) sort = models.ForeignKey(to="Sort", to_field="sid", null=True, on_delete=models.CASCADE) # 與標簽建立多對多關系 tag = models.ManyToManyField(to="Tag", through="ArticleToTag", through_fields=("article", "tag")) def __str__(self): return self.title class ArticleToTag(models.Model): aid = models.AutoField(primary_key=True) article = models.ForeignKey(to="Article", to_field="title", verbose_name="文章題目", on_delete=models.CASCADE) tag = models.ForeignKey(to="Tag", to_field="name", verbose_name="文章標簽", on_delete=models.CASCADE) def __str__(self): name = self.article.title + "---" + self.tag.name return name class Like(models.Model): """ 文章點贊表 """ lid = models.AutoField(primary_key=True) user = models.ForeignKey(to="User", to_field="uid", null=True, on_delete=models.CASCADE) article = models.ForeignKey(to="Article", to_field="aid", null=True, on_delete=models.CASCADE) is_like = models.BooleanField(default=True) class Comment(models.Model): """ 文章評論表 """ cid = models.AutoField(primary_key=True) user = models.ForeignKey(to="User", to_field="uid", null=True, on_delete=models.CASCADE) article = models.ForeignKey(to="Article", to_field="aid", null=True, on_delete=models.CASCADE) create_time = models.DateField(verbose_name="創建日期", auto_now_add=True) content = models.CharField(max_length=255, verbose_name="評論內容") parent_comment = models.ForeignKey(to="Comment", to_field="cid", null=True, on_delete=models.CASCADE) # 根評論 def __str__(self): return self.content
由於需要用到mysql,所以需要在setteings.py中配置數據庫信息
在第一張User表中,由於是繼承了AbstractUser,所以也需要配置信息
settings.py
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘blog‘, ‘USER‘: ‘root‘, ‘PASSWORD‘: ‘admin‘, ‘HOST‘: ‘localhost‘, ‘PORT‘: 3306 } } AUTH_USER_MODEL = "app01.User"
註意,使用mysql時需要在項目的init.py中添加如下代碼:
import pymysql
pymysql.install_as_MySQLdb()
3.功能開發
3.1 登錄驗證
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/blog/css/bootstrap.min.css">
<link rel="icon" href="/static/blog/image/favicon.ico">
<style type="text/css">
body {
background: url(../static/blog/image/bk.jpeg) no-repeat;
background-size: 100%;
overflow: hidden;
}
h3 {
padding: 5px;
border-bottom: 1px solid #ddd;
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-4 col-md-offset-4" style="margin-top: 100px">
<form>
<div class="well">
<h3 style="text-align: center">登錄界面</h3>
<div class="form-group">
<label for="username">用戶名</label>
<input type="text" class="form-control" id="username" placeholder="用戶名" autocomplete="off">
</div>
<div class="form-group">
<label for="password">密碼</label>
<input type="password" class="form-control" id="password" placeholder="密碼" autocomplete="off">
</div>
<div class="row form-group">
<div class="col-md-6">
<label for="password">驗證碼</label>
<input type="text" class="form-control" id="verify_code" placeholder="請輸入驗證碼" autocomplete="off">
</div>
<div class="col-md-6">
<label for="password"></label>
<img src="/verify_code" style="height: 40px;width: 183px">
</div>
</div>
<button type="button" class="btn btn-default">登錄</button>
</div>
</form>
</div>
</div>
</body>
</html>
views.py
from django.shortcuts import render, HttpResponse
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from io import BytesIO
def login(request):
return render(request, "login.html")
def random_color():
color = (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
return color
def random_color2():
color = (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
return color
def random_char():
"""
隨機數/字母
"""
random_num = str(random.randint(0, 9))
random_low = chr(random.randint(97, 122)) # a~z
random_upper = chr(random.randint(65, 90)) # A~Z
random_chars = random.choice([random_num, random_low, random_upper])
return random_chars
def verify_code(request):
"""
驗證碼
"""
image = Image.new("RGB", (183, 40), (255, 255, 255))
image_font = ImageFont.truetype("static/blog/font/Arial.ttf", 32)
draw = ImageDraw.Draw(image)
# 給每個坐標填充顏色
for x in range(183):
for y in range(40):
draw.point((x, y), fill=random_color())
for i in range(5):
draw.text((20+i*30, 0), random_char(), font=image_font, fill=random_color2())
image = image.filter(ImageFilter.BLUR) # 模糊處理
f = BytesIO()
image.save(f, "png")
data = f.getvalue()
return HttpResponse(data)
登錄界面效果如下圖所示:
Python學習之路—2018/7/10