Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
exclude: |
(?x)(
^venv/|
^alembic/|
^server.py
)
repos:
Expand Down
8 changes: 4 additions & 4 deletions alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import os
import sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../")

from logging.config import fileConfig

from sqlalchemy import engine_from_config, pool

from alembic import context
from configures.settings import SQLALCHEMY_DATABASE_URI
from models.database_model import Meta, User

sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../")

from models.database_models import *

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
Expand Down
100 changes: 100 additions & 0 deletions alembic/versions/b21d8d35b74c_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""message

Revision ID: b21d8d35b74c
Revises:
Create Date: 2020-05-16 18:10:35.550766

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'b21d8d35b74c'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('comment',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False, comment='评论用户的 ID'),
sa.Column('post_id', sa.Integer(), nullable=False, comment='Post 文章的 ID'),
sa.Column('content', sa.Text(), nullable=False, comment='用户的评论'),
sa.Column('create_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='创建时间'),
sa.Column('update_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='更新时间'),
sa.Column('deleted', sa.Boolean(), nullable=True, comment='改项目是否被删除'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('post',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('topic_id', sa.Integer(), nullable=False, comment='文章所在的主题 ID'),
sa.Column('user_id', sa.Integer(), nullable=False, comment='发布文章用户的 ID'),
sa.Column('content', sa.Text(), nullable=False),
sa.Column('click_times', sa.Integer(), nullable=True, comment='文章的点击数'),
sa.Column('tags', sa.JSON(), nullable=True, comment='文章的 tag'),
sa.Column('create_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='创建时间'),
sa.Column('update_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='更新时间'),
sa.Column('deleted', sa.Boolean(), nullable=True, comment='改项目是否被删除'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('topic',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=256), nullable=False),
sa.Column('create_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='创建时间'),
sa.Column('update_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='更新时间'),
sa.Column('deleted', sa.Boolean(), nullable=True, comment='该项目是否被删除'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(length=100), nullable=False),
sa.Column('password_hash', sa.String(length=256), nullable=False, comment='登陆密码 hash 之后的值'),
sa.Column('name', sa.String(length=100), nullable=True),
sa.Column('phone', sa.String(length=20), nullable=True, comment='电话号码'),
sa.Column('avatar', sa.String(length=256), nullable=True, comment='用户头像'),
sa.Column('website', sa.String(length=100), nullable=True, comment='个人网站'),
sa.Column('company', sa.String(length=100), nullable=True, comment='所在公司'),
sa.Column('job', sa.String(length=100), nullable=True, comment='职位'),
sa.Column('location', sa.String(length=100), nullable=True, comment='所在地'),
sa.Column('signature', sa.String(length=256), nullable=True, comment='签名'),
sa.Column('Dribbble', sa.String(length=256), nullable=True, comment='Dribbble'),
sa.Column('Duolingo', sa.String(length=256), nullable=True, comment='Duolingo'),
sa.Column('About_me', sa.String(length=256), nullable=True, comment='About.me'),
sa.Column('Last_me', sa.String(length=256), nullable=True, comment='Last.fm'),
sa.Column('Goodreads', sa.String(length=256), nullable=True, comment='Goodreads'),
sa.Column('GitHub', sa.String(length=256), nullable=True, comment='GitHub'),
sa.Column('PSN_ID', sa.String(length=256), nullable=True, comment='PSN ID'),
sa.Column('Steam_ID', sa.String(length=256), nullable=True, comment='Steam_ID'),
sa.Column('Twitch', sa.String(length=256), nullable=True, comment='Twitch'),
sa.Column('BattleTag', sa.String(length=256), nullable=True, comment='BattleTag'),
sa.Column('Instagram', sa.String(length=256), nullable=True, comment='Instagram'),
sa.Column('Telegram', sa.String(length=256), nullable=True, comment='Telegram'),
sa.Column('Twitter', sa.String(length=256), nullable=True, comment='Twitter'),
sa.Column('BTC_Address', sa.String(length=256), nullable=True, comment='BTC Address'),
sa.Column('Coding_net', sa.String(length=256), nullable=True, comment='Coding.net'),
sa.Column('Personal_Introduction', sa.String(length=256), nullable=True, comment='个人简介'),
sa.Column('state_update_view_permission', sa.Integer(), nullable=True, comment='状态更新查看权限'),
sa.Column('community_rich_rank', sa.Boolean(), nullable=True, comment='社区财富排行榜'),
sa.Column('money', sa.Integer(), nullable=True, comment='余额'),
sa.Column('show_remain_money', sa.Boolean(), nullable=True, comment='是否显示余额'),
sa.Column('use_avatar_for_favicon', sa.Boolean(), nullable=True, comment='使用节点头像作为页面 favicon'),
sa.Column('use_high_resolution_avatar', sa.Boolean(), nullable=True, comment='使用高精度头像'),
sa.Column('time_zone', sa.String(length=256), nullable=True, comment='默认使用的时区'),
sa.Column('create_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='创建时间'),
sa.Column('update_time', sa.DateTime(), server_default=sa.text('now()'), nullable=True, comment='更新时间'),
sa.Column('deleted', sa.Boolean(), nullable=True, comment='改项目是否被删除'),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('user')
op.drop_table('topic')
op.drop_table('post')
op.drop_table('comment')
# ### end Alembic commands ###
69 changes: 0 additions & 69 deletions alembic/versions/bfc7552a8070_message.py

This file was deleted.

6 changes: 3 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

from blueprints import all_blueprints
from configures import settings
from models import BaseModel
from models.database_model import db
from resourses import ApiResponse
from models.base_model import BaseModel
from models.database_models import db
from resources import ApiResponse

logger = logging.getLogger(__name__)

Expand Down
17 changes: 9 additions & 8 deletions blueprints/api.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
from flask import Blueprint
from flask_restful import Api

from resourses.user import User, Users
from resources.post import Post, Posts
from resources.topic import Topic, Topics
from resources.user import User, Users

api_bp = Blueprint("api", __name__, url_prefix="/api")


class CustomApiErrorClass(Exception):
@property
def custom_data(self):
return {'status': "failure", 'error': "None"}


api = Api(api_bp)

api.add_resource(User, "/users/<int:user_id>")
api.add_resource(Users, "/users")

api.add_resource(Topic, "/topics/<int:topic_id>")
api.add_resource(Topics, "/topics")

api.add_resource(Post, "/topics/<int:topic_id>/posts/<int:post_id>")
api.add_resource(Posts, "/topics/<int:topic_id>/posts")
2 changes: 2 additions & 0 deletions configures/const.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from configures import BaseEnumType

PER_PAGE = 50
POST_MINIMUM_WORDS = 5
BLANK = ""

DATE_FORMATS = [
Expand Down
7 changes: 6 additions & 1 deletion configures/help_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def is_allowed(cls, value: str) -> bool:
@classmethod
def check(cls, value: str):
if not cls.is_allowed(value):
raise exceptions.InvalidPattern(cls.ERROR_MSG)
raise exceptions.PatternInvalid(cls.ERROR_MSG)
return value


Expand All @@ -54,3 +54,8 @@ class EmailChecker(BaseChecker):
class PassWordChecker(BaseChecker):
ALLOWED_PATTERN = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*#?&]{8,}"
ERROR_MSG = "密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符,不能含有空格"


class BasicNameChecker(BaseChecker):
ALLOWED_PATTERN = '^[\\w\u4e00-\u9fa5-]+$'
ERROR_MSG = '名称中只允许出现【中文,英文,数字,下换线,连接符'
6 changes: 3 additions & 3 deletions exceptions/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ServerException(Exception):
code = 500


class InvalidArgument(ServerException):
class ArgumentInvalid(ServerException):
code = 400


Expand All @@ -17,9 +17,9 @@ class ObjectsDuplicated(ServerException):
code = 403


class ObjectsNotExisted(ServerException):
class ObjectsNotExist(ServerException):
code = 404


class InvalidPattern(ServerException):
class PatternInvalid(ServerException):
code = 403
12 changes: 7 additions & 5 deletions handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
from exceptions import exceptions

from models.database_model import Base as Model
from models.database_models.base_model import Base as Model


class BaseHandler:
_model = None

def __init__(self, id=None):
self.id = id
self.error_msg = f"{self._model.__name__} {self.id} 不存在"

def get_sqlalchemy_instance(self, error_msg=None) -> Model:
def assert_id_is_not_none(self):
if self.id is None:
raise exceptions.ServerException("id must not be None.")

def get_sqlalchemy_instance(self) -> Model:
self.assert_id_is_not_none()
instance = self._model.get_by_id(self.id)
if not instance or getattr(instance, 'deleted', False):
if not error_msg:
error_msg = "{model} {id} 不存在".format(model=self._model.__name__, id=self.id)
raise exceptions.ObjectsNotExisted(error_msg)
raise exceptions.ObjectsNotExist(self.error_msg)
return instance
Loading