Python学习之路—2018/7/10

Posted exburner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

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

技术分享图片

以上是关于Python学习之路—2018/7/10的主要内容,如果未能解决你的问题,请参考以下文章

[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段

机器学习之路: python 实践 word2vec 词向量技术

python学习之路01

python之路之前没搞明白4面向对象(封装)

python 机器学习有用的代码片段

Python学习之路——模块