mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2026-03-13 10:32:25 +08:00
fix tortoise-orm error
external link update examples
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
142
examples/example.sql
Normal 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
|
||||
125
examples/main.py
125
examples/main.py
@@ -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'
|
||||
)
|
||||
]
|
||||
|
||||
@@ -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}'
|
||||
|
||||
Reference in New Issue
Block a user