Python学习之路—2018/7/10

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)

登录界面效果如下图所示:

原文地址:https://www.cnblogs.com/ExBurner/p/9292153.html

时间: 2024-10-28 10:19:05

Python学习之路—2018/7/10的相关文章

Python学习之路—2018/7/11

Python学习之路-2018/7/10 3.功能开发 3.1 登录验证 login.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <t

Python学习之路—2018/6/29

Python学习之路-2018/6/29 1.跨表查询 跨表查询: 基于对象查询 基于双下划线查询 聚合和分组查询 F与Q查询 F查询 过滤器只能讲字段值与常量进行比较,如果需要用到与字段值进行比较则需要用到F查询,F查询还支持与常量之间的加减乘除的运算.数据: # 查询评论数大于阅读数的书籍 >>> Book.objects.filter(comment_count__gt=F("read_count")) <QuerySet [<Book: 斗破苍穹&

Python学习之路—2018/6/14

Python学习之路-2018/6/14 1.浏览器与服务器 浏览器向服务器发送请求的过程为请求过程,服务器向浏览器响应的过程为响应过程. 2.简单的web应用程序 import socket sock = socket.socket() sock.bind(("100.113.14.43", 8080)) sock.listen(5) with open("index.html", "r") as f: # 先将样式写入html文件中,然后再读

Python学习之路—2018/6/19

Python学习之路-2018/6/19 1.注册自定义转化器 converts.py class Birthday: regex = '[0-9]{8}' # 匹配规则 def to_python(self, value): # 匹配的字符串返回具体的变量值,传递到对应的视图函数中 return int(value) def to_url(self,value): # 反向解析 return "%04d" % value urls.py from django.urls import

Python学习之路—2018/6/26

Python学习之路-2018/6/26 1.ORM 单表操作 删除与修改记录 >>> ret = Book.objects.filter(title="go").delete() (1, {'app01.Book': 1}) >>> Book.objects.filter(price=115).update(price=120) 多表操作 创建模型 一对一 models.OneToOneField(to="表名", on_del

Python学习之路-Day1-Python基础

Python学习之路第一天 学习内容: 1.Python简介 2.安装 3.第一个Python程序 4.变量 5.字符编码 6.用户输入 7.表达式if..else语句 8.表达式for语句 9.break和continue 10.while循环 11.字符串格式化 1.python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承. 最新的TIOB

Python学习之路-装饰器&生成器&正则表达式

装饰器 通俗的讲,装饰器就是在不改变源代码基础上,给源代码增加新功能. 不改变函数的源代码.调用方式.返回值等,给函数增加新功能. 经典案例:登录装饰器, def login_decorator(func):     def inner():         if USER_TEMP["status"] == False:             print("\033[31;1m用户未登录,请先登录\033[0m")             login_atm()

Python 学习之路(二)

Python 学习之路(二) 以下所用的是Python 3.6 一.条件语句 简单判断 1 if 判断条件: 2 执行语句-- 3 else: 4 执行语句-- 复杂判断 1 if 判断条件1: 2 执行语句1-- 3 elif 判断条件2: 4 执行语句2-- 5 elif 判断条件3: 6 执行语句3-- 7 else: 8 执行语句4-- 二.循环语句 2.1 while语句 和其他语言一样,不同的是多了else语句.在 python 中,while - else 在循环条件为 false

Python 学习之路(三)

Python 学习之路(三) 以下所用的是Python 3.6 一.集合部分 集合是一个无序的,不重复的数据集合,主要用来去重,以及关系测试:交集,差集,并集等 1.1 关系操作 1.1.1 列表去重 可以给列表去重,例如: 1 set_demo = [1,2,3,4,5,3,2,1] # 列表 2 set_demo = set(set_demo) # 转换成集合,来去重 3 print(set_demo) 1.1.2 取交集 intersection()方法 可以获得两个集合的交集部分,例如: