mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-20 20:39:55 +00:00
修复数据库初始化和Schema类型匹配问题
This commit is contained in:
@@ -1,156 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
优化数据库Schema设计
|
||||
|
||||
修订 ID: optimize_schema_202412
|
||||
创建时间: 2024-12-19
|
||||
修订者: AI Assistant
|
||||
|
||||
变更内容:
|
||||
1. 统一字段长度限制
|
||||
2. 添加缺失的外键索引
|
||||
3. 优化字典数据缓存策略
|
||||
4. 统一布尔类型字段命名规范
|
||||
5. 标准化外键删除策略
|
||||
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# 修订标识符
|
||||
revision = 'optimize_schema_202412'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""应用优化变更"""
|
||||
|
||||
# 1. 统一用户表字段长度限制
|
||||
op.alter_column('system_users', 'username',
|
||||
existing_type=sa.VARCHAR(length=150),
|
||||
type_=sa.String(length=32),
|
||||
existing_nullable=False,
|
||||
existing_comment='用户名/登录账号')
|
||||
|
||||
op.alter_column('system_users', 'name',
|
||||
existing_type=sa.VARCHAR(length=40),
|
||||
type_=sa.String(length=32),
|
||||
existing_nullable=False,
|
||||
existing_comment='姓名')
|
||||
|
||||
op.alter_column('system_users', 'email',
|
||||
existing_type=sa.VARCHAR(length=255),
|
||||
type_=sa.String(length=64),
|
||||
existing_nullable=True,
|
||||
existing_comment='邮箱')
|
||||
|
||||
# 2. 添加creator_id索引
|
||||
op.create_index('ix_system_users_creator_id', 'system_users', ['creator_id'], unique=False)
|
||||
|
||||
# 3. 统一角色表字段长度
|
||||
op.alter_column('system_role', 'name',
|
||||
existing_type=sa.VARCHAR(length=40),
|
||||
type_=sa.String(length=32),
|
||||
existing_nullable=False,
|
||||
existing_comment='角色名称')
|
||||
|
||||
# 4. 统一部门表字段长度
|
||||
op.alter_column('system_dept', 'name',
|
||||
existing_type=sa.VARCHAR(length=40),
|
||||
type_=sa.String(length=32),
|
||||
existing_nullable=False,
|
||||
existing_comment='部门名称')
|
||||
|
||||
# 5. 优化字典表字段长度
|
||||
op.alter_column('system_dict_type', 'dict_name',
|
||||
existing_type=sa.VARCHAR(length=100),
|
||||
type_=sa.String(length=64),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典名称')
|
||||
|
||||
op.alter_column('system_dict_data', 'dict_label',
|
||||
existing_type=sa.VARCHAR(length=100),
|
||||
type_=sa.String(length=64),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典标签')
|
||||
|
||||
op.alter_column('system_dict_data', 'dict_value',
|
||||
existing_type=sa.VARCHAR(length=100),
|
||||
type_=sa.String(length=64),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典键值')
|
||||
|
||||
# 6. 添加菜单表索引优化
|
||||
op.create_index('ix_system_menu_parent_id', 'system_menu', ['parent_id'], unique=False)
|
||||
op.create_index('ix_system_menu_status', 'system_menu', ['status'], unique=False)
|
||||
|
||||
print("数据库Schema优化完成!")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""回滚优化变更"""
|
||||
|
||||
# 1. 恢复用户表字段长度
|
||||
op.alter_column('system_users', 'username',
|
||||
existing_type=sa.String(length=32),
|
||||
type_=sa.VARCHAR(length=150),
|
||||
existing_nullable=False,
|
||||
existing_comment='用户名/登录账号')
|
||||
|
||||
op.alter_column('system_users', 'name',
|
||||
existing_type=sa.String(length=32),
|
||||
type_=sa.VARCHAR(length=40),
|
||||
existing_nullable=False,
|
||||
existing_comment='姓名')
|
||||
|
||||
op.alter_column('system_users', 'email',
|
||||
existing_type=sa.String(length=64),
|
||||
type_=sa.VARCHAR(length=255),
|
||||
existing_nullable=True,
|
||||
existing_comment='邮箱')
|
||||
|
||||
# 2. 移除creator_id索引
|
||||
op.drop_index('ix_system_users_creator_id', table_name='system_users')
|
||||
|
||||
# 3. 恢复角色表字段长度
|
||||
op.alter_column('system_role', 'name',
|
||||
existing_type=sa.String(length=32),
|
||||
type_=sa.VARCHAR(length=40),
|
||||
existing_nullable=False,
|
||||
existing_comment='角色名称')
|
||||
|
||||
# 4. 恢复部门表字段长度
|
||||
op.alter_column('system_dept', 'name',
|
||||
existing_type=sa.String(length=32),
|
||||
type_=sa.VARCHAR(length=40),
|
||||
existing_nullable=False,
|
||||
existing_comment='部门名称')
|
||||
|
||||
# 5. 恢复字典表字段长度
|
||||
op.alter_column('system_dict_type', 'dict_name',
|
||||
existing_type=sa.String(length=64),
|
||||
type_=sa.VARCHAR(length=100),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典名称')
|
||||
|
||||
op.alter_column('system_dict_data', 'dict_label',
|
||||
existing_type=sa.String(length=64),
|
||||
type_=sa.VARCHAR(length=100),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典标签')
|
||||
|
||||
op.alter_column('system_dict_data', 'dict_value',
|
||||
existing_type=sa.String(length=64),
|
||||
type_=sa.VARCHAR(length=100),
|
||||
existing_nullable=False,
|
||||
existing_comment='字典键值')
|
||||
|
||||
# 6. 移除菜单表索引
|
||||
op.drop_index('ix_system_menu_parent_id', table_name='system_menu')
|
||||
op.drop_index('ix_system_menu_status', table_name='system_menu')
|
||||
|
||||
print("数据库Schema回滚完成!")
|
||||
@@ -27,7 +27,7 @@ class JobModel(CreatorMixin):
|
||||
start_date: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, comment='开始时间')
|
||||
end_date: Mapped[Optional[str]] = mapped_column(String(64), nullable=True, comment='结束时间')
|
||||
|
||||
job_logs: Mapped[Optional[list['JobLogModel']]] = relationship(back_populates="job", lazy="select")
|
||||
job_logs: Mapped[Optional[list['JobLogModel']]] = relationship(back_populates="job", lazy="selectin")
|
||||
|
||||
|
||||
class JobLogModel(MappedBase):
|
||||
@@ -50,4 +50,4 @@ class JobLogModel(MappedBase):
|
||||
job_id: Mapped[Optional[int]] = mapped_column(ForeignKey('monitor_job.id'), comment='任务ID')
|
||||
|
||||
# 任务关联关系
|
||||
job: Mapped[Optional["JobModel"]] = relationship(back_populates="job_logs", lazy="select")
|
||||
job: Mapped[Optional["JobModel"]] = relationship(back_populates="job_logs", lazy="selectin")
|
||||
|
||||
@@ -21,10 +21,10 @@ class DeptModel(ModelMixin):
|
||||
parent: Mapped[Optional["DeptModel"]] = relationship("DeptModel", cascade="all, delete-orphan", uselist=False)
|
||||
|
||||
# 角色关联关系
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_depts", back_populates="depts", lazy="select")
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_depts", back_populates="depts", lazy="selectin")
|
||||
|
||||
# 用户关联关系
|
||||
users: Mapped[List["UserModel"]] = relationship(back_populates="dept", lazy="select")
|
||||
users: Mapped[List["UserModel"]] = relationship(back_populates="dept", lazy="selectin")
|
||||
|
||||
# code: Mapped[Optional[str]] = mapped_column(String(20),nullable=True,unique=True,comment="部门编码")
|
||||
# leader_id: Mapped[Optional[int]] = mapped_column(Integer,nullable=True,comment="负责人ID")
|
||||
|
||||
@@ -17,7 +17,7 @@ class DictTypeModel(CreatorMixin):
|
||||
|
||||
dict_name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True, comment='字典名称')
|
||||
dict_type: Mapped[str] = mapped_column(String(100), nullable=False, unique=True, comment='字典类型')
|
||||
dict_datas: Mapped[List["DictDataModel"]] = relationship(back_populates="dict_type_rel", lazy="select")
|
||||
dict_datas: Mapped[List["DictDataModel"]] = relationship(back_populates="dict_type_rel", lazy="selectin")
|
||||
|
||||
|
||||
class DictDataModel(CreatorMixin):
|
||||
@@ -38,5 +38,5 @@ class DictDataModel(CreatorMixin):
|
||||
dict_type_id: Mapped[Optional[int]] = mapped_column(ForeignKey('system_dict_type.id'), nullable=True, comment='字典类型ID')
|
||||
|
||||
# 字典类型关联关系
|
||||
dict_type_rel: Mapped[Optional["DictTypeModel"]] = relationship(back_populates="dict_datas", lazy="select")
|
||||
dict_type_rel: Mapped[Optional["DictTypeModel"]] = relationship(back_populates="dict_datas", lazy="selectin")
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class MenuModel(ModelMixin):
|
||||
parent: Mapped[Optional['MenuModel']] = relationship(cascade='all, delete-orphan', primaryjoin="MenuModel.parent_id == MenuModel.id", uselist=False)
|
||||
|
||||
# 角色关联关系
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_menus", back_populates="menus", lazy="select")
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_menus", back_populates="menus", lazy="selectin")
|
||||
|
||||
# link: Mapped[Optional[str]] = mapped_column(String(255), comment='外链地址')
|
||||
# iframe: Mapped[Optional[str]] = mapped_column(String(255), comment='内嵌iframe地址')
|
||||
|
||||
@@ -23,7 +23,7 @@ class PositionModel(CreatorMixin):
|
||||
order: Mapped[int] = mapped_column(Integer, nullable=False, default=1, comment="显示排序")
|
||||
|
||||
# 用户关联关系
|
||||
users: Mapped[List["UserModel"]] = relationship(secondary="system_user_positions", back_populates="positions", lazy="select")
|
||||
users: Mapped[List["UserModel"]] = relationship(secondary="system_user_positions", back_populates="positions", lazy="selectin")
|
||||
|
||||
# users: Mapped[List["UserModel"]] = relationship(secondary="system_user_positions", back_populates="positions", lazy="select")
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class RoleModel(CreatorMixin):
|
||||
order: Mapped[int] = mapped_column(Integer, nullable=False, default=999, comment="显示排序")
|
||||
data_scope: Mapped[int] = mapped_column(Integer, nullable=False, default=1, comment="数据权限范围")
|
||||
|
||||
menus: Mapped[List["MenuModel"]] = relationship(secondary="system_role_menus", back_populates="roles", lazy="select")
|
||||
depts: Mapped[List["DeptModel"]] = relationship(secondary="system_role_depts", back_populates="roles", lazy="select")
|
||||
users: Mapped[List["UserModel"]] = relationship(secondary="system_user_roles", back_populates="roles", lazy="select")
|
||||
menus: Mapped[List["MenuModel"]] = relationship(secondary="system_role_menus", back_populates="roles", lazy="selectin")
|
||||
depts: Mapped[List["DeptModel"]] = relationship(secondary="system_role_depts", back_populates="roles", lazy="selectin")
|
||||
users: Mapped[List["UserModel"]] = relationship(secondary="system_user_roles", back_populates="roles", lazy="selectin")
|
||||
|
||||
|
||||
@@ -74,12 +74,12 @@ class UserModel(CreatorMixin):
|
||||
name: Mapped[str] = mapped_column(String(32),nullable=False,comment="昵称")
|
||||
mobile: Mapped[Optional[str]] = mapped_column(String(20),nullable=True,unique=True,comment="手机号")
|
||||
email: Mapped[Optional[str]] = mapped_column(String(64),nullable=True,unique=True,comment="邮箱")
|
||||
gender: Mapped[Optional[int]] = mapped_column(Integer,default=2,nullable=True,comment="性别(0:男 1:女 2:未知)")
|
||||
gender: Mapped[Optional[str]] = mapped_column(String(1), default='0',nullable=True,comment="性别(0:男 1:女 2:未知)")
|
||||
avatar: Mapped[Optional[str]] = mapped_column(String(500),nullable=True,comment="头像URL地址")
|
||||
is_superuser: Mapped[bool] = mapped_column(Boolean,default=False,nullable=False,comment="是否超管")
|
||||
last_login: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True),nullable=True,comment="最后登录时间")
|
||||
|
||||
dept_id: Mapped[Optional[int]] = mapped_column(Integer,ForeignKey('system_dept.id', ondelete="SET NULL", onupdate="CASCADE"),nullable=True, index=True, comment="部门ID")
|
||||
dept: Mapped[Optional["DeptModel"]] = relationship(back_populates="users",foreign_keys=[dept_id],lazy="select")
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_user_roles",back_populates="users",lazy="select")
|
||||
positions: Mapped[List["PositionModel"]] = relationship(secondary="system_user_positions",back_populates="users")
|
||||
dept: Mapped[Optional["DeptModel"]] = relationship(back_populates="users",foreign_keys=[dept_id],lazy="selectin")
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_user_roles",back_populates="users",lazy="selectin")
|
||||
positions: Mapped[List["PositionModel"]] = relationship(secondary="system_user_positions",back_populates="users",lazy="selectin")
|
||||
|
||||
@@ -278,7 +278,10 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
|
||||
|
||||
if 3 in data_scopes:
|
||||
# 3、本部门及以下数据
|
||||
dept_objs = await CRUDBase(DeptModel, self.auth).list()
|
||||
# 直接查询部门表,避免递归调用CRUD
|
||||
dept_sql = select(DeptModel)
|
||||
dept_result = await self.db.execute(dept_sql)
|
||||
dept_objs = dept_result.scalars().all()
|
||||
id_map = get_child_id_map(dept_objs)
|
||||
dept_child_ids = get_child_recursion(id=self.current_user.dept_id, id_map=id_map)
|
||||
for child_id in dept_child_ids:
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
提供跨数据库兼容的基础模型类和类型装饰器
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
import json
|
||||
from sqlalchemy import Boolean, String, Integer, DateTime, ForeignKey, Text, BigInteger
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.asyncio import AsyncAttrs
|
||||
from sqlalchemy.orm import relationship, DeclarativeBase, Mapped, declared_attr, mapped_column
|
||||
from sqlalchemy.types import TypeDecorator
|
||||
@@ -61,7 +63,7 @@ class CreatorMixin(ModelMixin):
|
||||
return relationship(
|
||||
"UserModel",
|
||||
primaryjoin=f"{cls.__name__}.creator_id == UserModel.id",
|
||||
lazy="select",
|
||||
lazy="selectin",
|
||||
foreign_keys=[cls.creator_id],
|
||||
viewonly=True
|
||||
)
|
||||
@@ -8,11 +8,7 @@
|
||||
"dept_id": 1
|
||||
},
|
||||
{
|
||||
"role_id": 3,
|
||||
"dept_id": 1
|
||||
},
|
||||
{
|
||||
"role_id": 3,
|
||||
"role_id": 2,
|
||||
"dept_id": 6
|
||||
}
|
||||
]
|
||||
@@ -1,346 +1,346 @@
|
||||
[
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 1
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 2
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 3
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 4
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 5
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 6
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 7
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 8
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 9
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 10
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 11
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 12
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 13
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 14
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 15
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 16
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 17
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 18
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 19
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 20
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 21
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 22
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 23
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 24
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 25
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 26
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 27
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 28
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 29
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 30
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 31
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 32
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 33
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 34
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 35
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 36
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 37
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 38
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 39
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 40
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 41
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 42
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 43
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 44
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 45
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 46
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 47
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 48
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 49
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 50
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 51
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 52
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 53
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 54
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 55
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 56
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 57
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 58
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 59
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 60
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 61
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 62
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 63
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 64
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 65
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 66
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 67
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 68
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 69
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 70
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 71
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 72
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 73
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 74
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 75
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 76
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 77
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 78
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 79
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 80
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 81
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 82
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 83
|
||||
},
|
||||
{
|
||||
"role_id": 2,
|
||||
"role_id": 1,
|
||||
"menu_id": 84
|
||||
},
|
||||
{
|
||||
"role_id": 3,
|
||||
"role_id": 2,
|
||||
"menu_id": 1
|
||||
},
|
||||
{
|
||||
"role_id": 3,
|
||||
"role_id": 2,
|
||||
"menu_id": 2
|
||||
}
|
||||
]
|
||||
@@ -8,7 +8,7 @@
|
||||
"position_id": 7
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"user_id": 3,
|
||||
"position_id": 1
|
||||
}
|
||||
]
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import uuid
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
Reference in New Issue
Block a user