fix tortoise-orm error

external link
update examples
This commit is contained in:
long2ice
2020-04-13 16:15:49 +08:00
parent 3739271b89
commit 868177fa09
20 changed files with 459 additions and 286 deletions

View File

@@ -1,9 +1,3 @@
from tortoise import fields, Model
class BaseModel(Model):
create_at = fields.DatetimeField(auto_now_add=True, description='创建时间')
update_at = fields.DatetimeField(auto_now=True, description='更新时间')
class Meta:
abstract = True

View File

@@ -1,60 +1,15 @@
from enum import IntEnum
class EnumMixin:
@classmethod
def choices(cls):
raise NotImplementedError
from fastapi_admin.enum import EnumMixin
class Status(EnumMixin, IntEnum):
"""
状态
"""
on = 1
off = 0
class ProductType(EnumMixin, IntEnum):
article = 1
page = 2
@classmethod
def choices(cls):
return {
cls.on: '开启',
cls.off: '关闭'
}
class BaiduAiCategory(EnumMixin, IntEnum):
id_card = 1
censor = 2
@classmethod
def choices(cls):
return {
cls.id_card: '身份证',
cls.censor: '审核'
}
class AliYunSecretCategory(EnumMixin, IntEnum):
sms = 1
oss = 2
alert = 3
@classmethod
def choices(cls):
return {
cls.sms: '短信',
cls.oss: 'oss',
cls.alert: '报警'
}
class DeviceSys(EnumMixin, IntEnum):
android = 1
ios = 2
@classmethod
def choices(cls):
return {
cls.android: '安卓',
cls.ios: 'iOS',
cls.article: 'Article',
cls.page: 'Page'
}

142
examples/example.sql Normal file
View File

@@ -0,0 +1,142 @@
-- MySQL dump 10.13 Distrib 8.0.19, for osx10.15 (x86_64)
--
-- Host: 127.0.0.1 Database: fastapi-admin
-- ------------------------------------------------------
-- Server version 8.0.19
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `category`
--
DROP TABLE IF EXISTS `category`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `category` (
`id` int NOT NULL AUTO_INCREMENT,
`slug` varchar(200) NOT NULL,
`name` varchar(200) NOT NULL,
`created_at` datetime(6) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `category`
--
LOCK TABLES `category` WRITE;
/*!40000 ALTER TABLE `category` DISABLE KEYS */;
INSERT INTO `category` VALUES (1,'test','test','2020-04-13 15:16:25.000000'),(2,'test','test','2020-04-13 15:16:25.000000'),(3,'test','test','2020-04-13 15:16:25.000000'),(4,'test','test','2020-04-13 15:16:25.000000'),(5,'test','test','2020-04-13 15:16:25.000000'),(6,'test','test','2020-04-13 15:16:25.000000'),(7,'test','test','2020-04-13 15:16:25.000000'),(8,'test','test','2020-04-13 15:16:25.000000'),(9,'test','test','2020-04-13 15:16:25.000000');
/*!40000 ALTER TABLE `category` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `product`
--
DROP TABLE IF EXISTS `product`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `product` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`view_num` int NOT NULL,
`sort` int NOT NULL,
`is_reviewed` tinyint(1) NOT NULL,
`type` smallint NOT NULL COMMENT 'article: 1\npage: 2',
`image` varchar(200) NOT NULL,
`body` longtext NOT NULL,
`created_at` datetime(6) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `product`
--
LOCK TABLES `product` WRITE;
/*!40000 ALTER TABLE `product` DISABLE KEYS */;
INSERT INTO `product` VALUES (1,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(2,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(3,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(4,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(5,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(6,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(7,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(8,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000'),(9,'Phone',10,1,1,1,'https://github.com/long2ice/fastapi-admin','test','2020-04-13 15:16:56.000000');
/*!40000 ALTER TABLE `product` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `product_category`
--
DROP TABLE IF EXISTS `product_category`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `product_category` (
`product_id` int NOT NULL,
`category_id` int NOT NULL,
KEY `product_id` (`product_id`),
KEY `category_id` (`category_id`),
CONSTRAINT `product_category_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`) ON DELETE CASCADE,
CONSTRAINT `product_category_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `product_category`
--
LOCK TABLES `product_category` WRITE;
/*!40000 ALTER TABLE `product_category` DISABLE KEYS */;
INSERT INTO `product_category` VALUES (1,1);
/*!40000 ALTER TABLE `product_category` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `user`
--
DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(200) NOT NULL,
`last_login` datetime(6) NOT NULL COMMENT 'Last Login',
`is_active` tinyint(1) NOT NULL COMMENT 'Is Active',
`avatar` varchar(200) NOT NULL,
`intro` longtext NOT NULL,
`created_at` datetime(6) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `user`
--
LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'long2ice','$2b$12$CD5ImAgBr7TZpJABxuXASOXz/cAFMIhXsmnZCU.cvo/c.kOOpSkXq','2020-04-13 12:44:06.000000',1,'https://c-ssl.duitang.com/uploads/item/201901/09/20190109072726_aNNZd.thumb.1000_0.jpeg','test','2020-04-13 12:44:14.000000');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-04-13 15:27:30

View File

@@ -1,14 +1,16 @@
import uvicorn
from fastapi import FastAPI
from fastapi import FastAPI, Depends
from starlette.middleware.cors import CORSMiddleware
from tortoise.contrib.fastapi import register_tortoise
from tortoise.contrib.pydantic import pydantic_queryset_creator
from fastapi_admin.depends import get_model
from fastapi_admin.factory import app as admin_app
from fastapi_admin.schemas import BulkIn
from fastapi_admin.site import Site, Menu
TORTOISE_ORM = {
'connections': {
'default': 'mysql://root:123456@127.0.0.1:3306/micro'
'default': 'mysql://root:123456@127.0.0.1:3306/fastapi-admin'
},
'apps': {
'models': {
@@ -19,11 +21,23 @@ TORTOISE_ORM = {
}
@admin_app.post(
'/{resource}/bulk/test_bulk'
)
async def test_bulk(
bulk_in: BulkIn,
model=Depends(get_model)
):
qs = model.filter(pk__in=bulk_in.pk_list)
pydantic = pydantic_queryset_creator(model)
ret = await pydantic.from_queryset(qs)
return ret.dict()
def create_app():
fast_app = FastAPI(debug=True)
register_tortoise(fast_app, config=TORTOISE_ORM)
register_tortoise(fast_app, config=TORTOISE_ORM, generate_schemas=True)
fast_app.mount('/admin', admin_app)
admin_app.init(
@@ -31,92 +45,71 @@ def create_app():
admin_secret='test',
models='examples.models',
site=Site(
name='微服务管理后台',
name='FastAPI-admin Demo',
logo='https://github.com/long2ice/fastapi-admin/raw/master/front/static/img/logo.png',
locale='zh-CN',
locale_switcher=False,
locale='en-US',
locale_switcher=True,
menu=[
Menu(
name='首页',
name='Home',
url='/',
icon='fa fa-home'
),
Menu(
name='配置',
name='Content',
title=True
),
Menu(
name='应用',
url='/rest/App',
icon='fa fa-pencil',
sort_fields=('uaid',),
search_fields=('uaid',),
name='Product',
url='/rest/Product',
icon='icon-list',
search_fields=('type',),
fields_type={
'type': 'radiolist'
},
bulk_actions=[
{
'value': 'delete',
'text': 'delete_all',
}
, {
'value': 'test_bulk',
'text': 'TestBulk'
}
]
),
Menu(
name='多对多测试',
url='/rest/ManyToManyTest'
name='Category',
url='/rest/Category',
icon='icon-list'
),
Menu(
name='阿里云秘钥',
url='/rest/AliYunSecret',
icon='fa fa-user-secret'
),
Menu(
name='阿里云OSS',
url='/rest/AliYunOss',
icon='fa fa-database'
),
Menu(
name='App短信',
url='/rest/AppSms',
icon='fa fa-envelope-o',
search_fields=('app',)
),
Menu(
name='百度AI',
url='/rest/BaiduAi',
icon='fa fa-desktop'
),
Menu(
name='App百度AI',
url='/rest/AppBaiduAi',
icon='fa fa-laptop',
),
Menu(
name='在线参数',
url='/rest/Config',
icon='fa fa-cog',
actions={
'delete': False
}
),
Menu(
name='基本信息',
name='External',
title=True
),
Menu(
name='请求日志',
url='/rest/ApiLog',
icon='fa fa-sticky-note',
search_fields=('app',),
name='Github',
url='https://github.com/long2ice/fastapi-admin',
icon='fa fa-github',
external=True
),
Menu(
name='App版本',
url='/rest/AppVersion',
icon='fa fa-mobile'
),
Menu(
name='授权',
name='Auth',
title=True
),
Menu(
name='用户',
name='User',
url='/rest/User',
icon='fa fa-user'
icon='fa fa-user',
fields_type={
'avatar': 'image'
},
exclude=('password',),
search_fields=('username',)
),
Menu(
name='注销',
url='/login',
name='Logout',
url='/logout',
icon='fa fa-lock'
)
]

View File

@@ -1,94 +1,39 @@
from tortoise import fields
from tortoise import fields, Model
from . import BaseModel
from .enums import AliYunSecretCategory, BaiduAiCategory, Status, DeviceSys
from fastapi_admin.models import User as AdminUser
from .enums import ProductType
class User(AdminUser, BaseModel):
last_login = fields.DatetimeField(description='上次登录')
class User(AdminUser, Model):
last_login = fields.DatetimeField(description='Last Login')
is_active = fields.BooleanField(default=True, description='Is Active')
avatar = fields.CharField(max_length=200)
intro = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
def __str__(self):
return f'{self.pk}#{self.username}'
class AliYunSecret(BaseModel):
app_id = fields.CharField(max_length=50)
app_secret = fields.CharField(max_length=50)
category = fields.IntEnumField(AliYunSecretCategory, description='类别', default=AliYunSecretCategory.sms)
class AliYunOss(BaseModel):
bucket = fields.CharField(max_length=50, unique=True, description='仓库')
domain = fields.CharField(max_length=200, description='域名')
endpoint = fields.CharField(max_length=200, description='端点')
aliyun_secret = fields.ForeignKeyField('models.AliYunSecret', related_name='aliyunoss')
class App(BaseModel):
uaid = fields.IntField(unique=True)
label = fields.CharField(max_length=20)
secret = fields.CharField(max_length=16, description='通信密钥')
work_secret = fields.CharField(max_length=100, description='企业微信密钥')
class Category(Model):
slug = fields.CharField(max_length=200)
name = fields.CharField(max_length=200)
created_at = fields.DatetimeField(auto_now_add=True)
def __str__(self):
return f'{self.uaid}#{self.label}'
return f'{self.pk}#{self.name}'
class AppSms(BaseModel):
app = fields.ForeignKeyField('models.App', related_name='app_sms')
scene = fields.CharField(max_length=50, description='使用场景')
aliyun_secret = fields.ForeignKeyField('models.AliYunSecret', related_name='app_sms')
sign_name = fields.CharField(max_length=20, description='签名')
template_code = fields.CharField(max_length=20, description='模板编号')
class Meta:
unique_together = (('app', 'scene'),)
class BaiduAi(BaseModel):
app_id = fields.CharField(max_length=50)
api_key = fields.CharField(max_length=50)
app_secret = fields.CharField(max_length=50)
category = fields.IntEnumField(BaiduAiCategory, description='应用类别', default=BaiduAiCategory.id_card)
class Product(Model):
categories = fields.ManyToManyField('models.Category')
name = fields.CharField(max_length=50)
view_num = fields.IntField(description='View Num')
sort = fields.IntField()
is_reviewed = fields.BooleanField(description='Is Reviewed')
type = fields.IntEnumField(ProductType, description='Product Type')
image = fields.CharField(max_length=200)
body = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
def __str__(self):
return f'{self.pk}#{self.app_id}'
class AppBaiduAi(BaseModel):
app = fields.ForeignKeyField('models.App', related_name='app_baidu_ais')
baidu_ai = fields.ForeignKeyField('models.BaiduAi', related_name='app_baidu_ais')
class Config(BaseModel):
label = fields.CharField(max_length=200)
key = fields.CharField(max_length=20)
value = fields.JSONField()
status: Status = fields.IntEnumField(Status, default=Status.on, description='状态')
class ApiLog(BaseModel):
app = fields.ForeignKeyField('models.App', related_name='api_logs')
endpoint = fields.CharField(max_length=50)
success = fields.BooleanField(default=True, description='是否成功')
status_code = fields.SmallIntField(description='状态码')
class AppVersion(BaseModel):
app = fields.ForeignKeyField('models.App', related_name='app_versions')
channel = fields.CharField(max_length=20, description='渠道')
device_sys = fields.IntEnumField(DeviceSys, default=DeviceSys.android, description='操作系统')
version_code = fields.CharField(max_length=20, description='版本号')
describe = fields.CharField(max_length=200, description='描述')
download_url = fields.CharField(max_length=200, description='下载链接')
is_update = fields.BooleanField(default=False, description='是否更新')
class Meta:
ordering = ['-id']
indexes = (('app', 'device_sys', 'channel'),)
class ManyToManyTest(BaseModel):
apps = fields.ManyToManyField('models.App')
label = fields.CharField(max_length=200)
return f'{self.pk}#{self.name}'