数据库设计
ER-Diagram
ORM
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
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")):
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()]}