Flask+React 实现一个简单前后分离博客系统[后端篇] 02.数据库模型

数据库设计

ER-Diagram

ER图

ORM

# models.py
from collections import OrderedDict
from datetime import datetime

from flask import current_app
from flask_sqlalchemy import BaseQuery, SQLAlchemy
from werkzeug.security import check_password_hash, generate_password_hash

# utils.py
# import os
# import base64
# def generate_base64_unique_id(size=32):
#	return base64.url_b64encode(os.urandom(64)).decode().rstrip("=")[:size]
from utils import generate_base64_unique_id


db = SQLAlchemy()


class Source(Enum):
    """文章来源"""

    # 原创文章
    ORIGINAL = "original"
    # 转载文章
    REPRODUCTION = "reproduction"
    # 翻译
    TRANSLATION = "translation"

    @staticmethod
    def is_valid_source(source):
        return source in [Source.ORIGINAL, Source.REPRODUCTION, Source.TRANSLATION]


class User(db.Model):
    """用户"""

    PAGE_SIZE = 10

    __tablename__ = "users"

    id = db.Column(db.String(32), primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    hashed_passwd = db.Column(db.String(255))

    articles = db.relationship("Article", backref=db.backref("author"))

    last_login = db.Column(db.DateTime, default=datetime.now)
    registered = db.Column(db.DateTime, default=datetime.now)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        if kwargs.get("password") is not None:
            self.hashed_passwd = generate_password_hash(kwargs.get("password"))

    def __repr__(self):
        return f"<User {self.username}>"

    def __str__(self):
        return self.username

    @staticmethod
    def insert_user(email, username, password):
        if not email or not username or not password:
            return False

        user = User(id=generate_base64_unique_id(),
                    email=email, username=username,
                    hashed_passwd=generate_password_hash(password))

        db.session.add(user)
        db.session.commit()

        return True

    def serialize(self):
        """序列化对象"""
        return OrderedDict(**{
    
    
            "id": self.id,
            "username": self.username,
            "email": self.email,
            "last_login": self.last_login,
            "registered": self.registered,
        })

    @staticmethod
    def insert_admin():
        user = User(email=current_app.config["ADMIN_EMAIL"], username=current_app.config["ADMIN_USERNAME"],
                    password=current_app.config["ADMIN_PASSWORD"])
        db.session.add(user)
        db.session.commit()


class Category(db.Model):
    """文章分类"""

    __tablename__ = "categories"
    id = db.Column(db.String(32), primary_key=True)
    name = db.Column(db.String(64))
    description = db.Column(db.Text, nullable=True)

    updated = db.Column(db.DateTime, default=datetime.now)
    created = db.Column(db.DateTime, default=datetime.now)

    __mapper_args__ = {
    
    "order_by": [created.desc(), updated.desc()]}


class Tag(db.Model):
    """文章标签"""

    __tablename__ = "tags"
    id = db.Column(db.String(32), primary_key=True)
    name = db.Column(db.String(50), unique=True, index=True, nullable=False)

    updated = db.Column(db.DateTime, default=datetime.now)
    created = db.Column(db.DateTime, default=datetime.now)

    __mapper_args__ = {
    
    "order_by": [created.desc(), updated.desc()]}

    def __repr__(self):
        return f"<Tag {self.name}>"

    def __str__(self):
        return self.name


class Article(db.Model):
    """文章"""
    __tablename__ = "articles"

    PAGE_SIZE = 10

    id = db.Column(db.String(32), primary_key=True)
    title = db.Column(db.String(128), index=True)
    summary = db.Column(db.Text)
    content_html = db.Column(db.Text)
    source = db.Column(db.String(12))

    # 阅读量
    viewed = db.Column(db.Integer, default=0)
    # 是否已发布
    is_published = db.Column(db.Boolean, default=False)
    # 作者
    author_id = db.Column(db.String(32), db.ForeignKey('users.id'))

    categories = db.relationship("Category", secondary="article_category_relations",
                                 backref=db.backref("articles"))
    tags = db.relationship("Tag", secondary="article_tag_relations",
                           backref=db.backref("articles"))

    updated = db.Column(db.DateTime, default=datetime.now)
    created = db.Column(db.DateTime, default=datetime.now)

    __mapper_args__ = {
    
    "order_by": [created.desc(), updated.desc()]}

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        if Source.is_valid_source(kwargs.get("source")):
            # check source
            raise ValueError

    def __repr__(self):
        return f"<Article {self.title}>"

    def __str__(self):
        return self.title


class ArticleTagRelation(db.Model):
    """文章标签关系"""

    __tablename__ = "article_tag_relations"
    id = db.Column(db.String(32), primary_key=True)
    article_id = db.Column(db.String(32), db.ForeignKey("articles.id"),
                           primary_key=True)
    tag_id = db.Column(db.String(32), db.ForeignKey("tags.id"),
                       primary_key=True)

    updated = db.Column(db.DateTime, default=datetime.now)
    created = db.Column(db.DateTime, default=datetime.now)

    __mapper_args__ = {
    
    "order_by": [created.desc(), updated.desc()]}


class ArticleCategoryRelation(db.Model):
    """文章分类关系"""

    __tablename__ = "article_category_relations"
    id = db.Column(db.String(32), primary_key=True)
    category_id = db.Column(db.String(32), db.ForeignKey("categories.id"),
                            primary_key=True)
    article_id = db.Column(db.String(32), db.ForeignKey("articles.id"),
                           primary_key=True)

    updated = db.Column(db.DateTime, default=datetime.now)
    created = db.Column(db.DateTime, default=datetime.now)

    __mapper_args__ = {
    
    "order_by": [created.desc(), updated.desc()]}

猜你喜欢

转载自blog.csdn.net/qq_35104586/article/details/106181183