基于Dectate和FastAPI的低代码API框架
项目描述
Aurelix:基于FastAPI、Dectate和SQLAlchemy的低代码API框架
Aurelix是一个用于快速构建用于存储数据和文件API的低代码框架。它建立在FastAPI和SQLAlchemy之上,并从Morepath的Dectate库中继承了一些扩展功能,基本上是将MorpFW的所有核心思想重写到一个新的框架中,以解决原始实现中的缺陷和问题。
Aurelix使用YAML以声明方式定义可组合的数据模型,并将其解释为遵循一定程度JSONAPI规范的RESTful API。
通过YAML可定义的能力包括
- 数据结构 - 您可以定义字段,这些字段将被解释为表列。
- 内置CRUD视图 - 通过Aurelix包含的常用
GET
、PUT
、PATCH
、DELETE
操作以及带有分页的搜索URL来节省编写RESTful CRUD视图的时间。 - 自定义视图 - 通过自定义视图扩展您的应用程序和模型,您可以引用模块中的函数,或者只需在YAML中放置代码。
- OIDC集成 - 如果您正在使用提供OIDC发现端点的OIDC提供程序,您可以使用该OIDC提供程序进行身份验证。
- 集合范围权限过滤 - 您可以指定特定角色的
where
过滤器,该过滤器将应用于不同角色,以允许或阻止它们查看您数据的具体部分。 - 字段权限过滤 - 您可以指定特定角色的字段权限,以限制按角色访问字段(
readWrite
、readOnly
、restricted
)。 - 字段转换链 - 您可以指定字段输入和输出转换链,例如,在存储到数据库之前加密和解密数据。
- 模型转换链 - 与字段转换链类似,但这是针对整个记录的应用。
- 字段验证链 - 在创建/更新时注册自定义函数以验证字段值。
- 对象存储集成 - 使用字符串字段作为对象存储引用字段,与基于S3/MinIO的对象存储集成,通过预签名URL进行上传和下载。
- 状态机 - 为您的模型定义状态机工作流程链以跟踪状态,包括在状态更改时触发的自定义函数。
- 事件钩子 - 将函数注册到
create
、update
和delete
相关事件上。
此外,如果您是数据工程师并且需要良好地管理数据模型版本和迁移,Aurelix 使用 Alembic 集成来管理数据模型的版本。
Aurelix 还拥有自己的客户端库,它可以帮助您轻松地与 API 服务器交互,您可以使用它来编写代码生成 ETL 或其他集成过程。
安装
Aurelix 需要 Python 3.11+
安装完整服务器
$ pip install aurelix[server]
仅安装客户端库使用
$ pip install aurelix
初始化应用程序
要初始化应用程序,您可以运行
$ aurelix init myproject
然后使用以下命令启动它
$ cd myproject/
$ alembic revision --autogenerate -m "initial model"
$ alembic upgrade head
$ export AURELIX_CONFIG=`pwd`/app.yaml
$ aurelix run
示例应用程序
此示例展示了 Aurelix 的一些功能。详细文档仍在进行中。
此示例应用程序的项目目录如下所示
myproject/
`- app.yaml
`- models/
`- mymodel.yaml
`- libs/
`- myviews.py
app.yaml
的内容
spec_version: app/0.1
title: MyApp
databases:
- name: default
url: sqlite:///./database.sqlite
libs/myviews.py
的内容。Aurelix 配置可以从 libs/
目录加载视图和模块
from fastapi import Request
async def myview(request: Request):
return {
'hello': 'world'
}
models/mymodel.yaml
的内容。从模型自动创建 API 是 Aurelix 功能的核心
spec_version: model/0.1
name: mymodel
storageType:
name: sqlalchemy
database: default
fields:
title:
title: Title
dataType:
type: string
size: 128
required: true
workflowStatus:
title: Workflow Status
dataType:
type: string
size: 64
required: true
indexed: true
views:
extensions:
- '/+custom-view':
method: GET
handler:
function: myviews:myview
tags:
- custom tag
启动服务
使用 Docker
$ docker run -v /path/to/myproject:/opt/app -p 8000:8000 -ti --rm docker.io/kagesenshi/aurelix:latest
使用 aurelix
命令
$ export AURELIX_CONFIG='/path/to/myproject/app.yaml'
$ aurelix run -l 0.0.0.0
配置规范
Aurelix 通过 YAML 配置来组合应用程序和模型。这允许框架和应用程序之间的解耦,并为 YAML 生成自动化铺平道路。
应用程序配置
app.yaml
定义了有关应用程序的元数据,包括 FastAPI 的应用程序元数据(应用程序标题、摘要、目录、swagger UI 初始化 oauth 配置)、应用程序将连接到的数据库列表以及要在应用程序根处注册的视图函数列表。以下示例展示了可以在 app.yaml
上定义的一些选项
spec_version: app/0.1
title: Application
summary: My sample app
version: 0.1.0
terms_of_service:
model_directory: models # directory to model YAML spec, relative to app.yaml
libs_directory: libs # directory to libs directory, relative to app.yaml
databases: # sqlalchemy database connections to create for the app
- name: default
type: sqlalchemy
url: sqlite:///./database.sqlite
# url_env: DB_URL # environment variable that stores the database url
object_stores:
- name: default
type: minio # type of object storage, we only support MinIO or MinIO compatible servers for now.
endpoint_url: http://localhost:9000
# endpoint_url_env: S3_ENDPOINT # environment variable that stores endpoint url
access_key: accesskey # object storage access key
secret_key: secretkey # object storage secret key
# access_key_env: S3_ACCESS_KEY # environment variable that stores the access key
# secret_key_env: S3_SECRET_KEY # environment variable that stores the secret key
swagger_ui_init_oauth: # set this if you want to enable swagger UI OIDC auth
client_id: # oidc client ID for swagger UI
client_secret: # oidc client secret for swagger UI
oidc_discovery_endpoint: # url to .well-known/openid-configuration of OIDC provider to use as external token provider
views:
extensions: # view registry on the root of the app. use this place add views on your app that is not attached to a model
'/+hello':
method: 'GET'
handler:
code: |
def function(request: Request):
return {'message': 'boo'}
有关 app.yaml
规范的更多详细信息,请参阅 配置选项 中的 AppSpec
。
模型配置
模型配置是 Aurelix 功能的核心,因为 Aurelix 在数据模型规范之上生成 API。
name: mymodel # name of the model, this translates to database table name for sqlalchemy storage
storage_type:
name: sqlalchemy # type of storage to use, for now we only have sqlalchemy
database: default # name of storage
fields: # this contain the list of fields you want to have in your model.
title:
title: Title
data_type:
type: string
size: 128
required: true
default: null
indexed: false
unique: false
validators: # validator chain
- code: |
from aurelix import exc
def function(collection, value, data):
# collection: refers to collection object
# value: value of the field to validate
# data: refers to full model data to validate
if not value.startswith('prefix'):
raise exc.ValidationError("Invalid title")
- function: mypackage.mymodule:myfunction # you can also specify reference to function in python module
encodedString: # you can transform field value before storing into db and when loading from db
title: Encoded string
data_type:
type: string
size: 128
required: false
default: null
indexed: false
unique: false
input_transformers: # input serialization transform chain before storing in database
- code: |
import base64
def function(collection, value, data):
return base64.b64encode(value.encode('utf8')).decode('utf8')
output_transformers: # output deserialization transform chain before returning to user
- code: |
import base64
def function(collection, value, data):
return base64.b64decode(value.encode('utf8')).decode('utf8')
selectionField: # you can also specify enum fields
title: Selection field
dataType:
type: string
size: 128
enum:
- value: option1
label: Option 1 Title
- value: option2
label: Option 2 Title
fileUpload: # you can create a string field for referencing to object storage data. refer to objectStore option on the model level below
title: File Upload
data_type:
type: string
size: 128
objectStore: # this contains objectStore settings for each field
fileUpload:
type: minio # type of object storage, we only support MinIO or MinIO compatible servers for now.
endpoint_url: http://localhost:9000
bucket: mybucket
access_key_env: S3_ACCESS_KEY # environment variable that stores the access key
secret_key_env: S3_SECRET_KEY # environment variable that stores the secret key
validators: # validation chain on the model itself
- code: |
from aurelix import exc
def function(collection, data):
# collection: refers to collection object
# data: refers to full model data to validate
pass
default_field_permission: readWrite # default permission to all fields
permission_filters: # permission filtering rules. it is evaluated from top to bottom
# row filtering by roles
- identities:
- 'role:mygroup'
where_filter: title like '%postfix' # use SQL where statement here for sqlalchemy storage
- identities:
- '*' # all identities
where_filter: 0=1
# column filtering by roles
- identities:
- 'role:group1'
default_field_permission: restricted
read_write_fields:
- title
read_only_fields:
- fileUpload
- identities:
- 'role:group2'
default_field_permission: readWrite
restricted_fields:
- title
- identities:
- '*'
default_field_permission: restricted
views: # views registry for the model
listing:
enabled: true
max_page_size: 100
create:
enabled: true
read:
enabled: true
update:
enabled: true
delete:
enabled: true
extensions: # custom views registry. views registered here is relative to the collection
'/+hello':
method: 'GET'
handler:
code: | # you can use fastapi dependency injection here
def function(request: Request, collection: Collection):
return {'message': 'collection view'}
'/{identifier}/+hello': # this view is attached to model
method: 'GET'
handler:
code: | # you can use fastapi dependency injection here
def function(request: Request, collection: Collection, model: Model):
return {'message': 'model view'}
tags:
- mytag # openapi tag to group all views as
stateMachine: # if you want statemachine on +transition view, configure it here. it uses pytransition internally.
initial_state: new
field: workflowStatus
states:
- value: new
label: New
- value: running
label: Processing
- value: completed
label: Completed
- value: failed
label: Failed
on_enter: # you can trigger functions on state enter/exit
code: |
from aurelix.crud.base import StateMachine
def function(sm: StateMachine):
request = sm.request
item = sm.item
# do something here
on_exit:
code: |
from aurelix.crud.base import StateMachine
def function(sm: StateMachine):
request = sm.request
item = sm.item
# do something here
- value: terminated
label: Cancelled
transitions:
- trigger: start
label: Start
source: new
dest: running
- trigger: stop
label: Stop
source: running
dest: terminated
- trigger: complete
label: Mark as completed
source: running
dest: completed
- trigger: fail
label: Mark as failed
source: runnning
dest: failed
before_create:
- code: |
def function(collection, data: dict):
# do something here
pass
after_create:
- code: |
def function(collection, item: Model):
# do something here
pass
before_update:
- code: |
def function(collection, data: dict):
# do something here
pass
after_update:
- code: |
def function(collection, item: Model):
# do something here
pass
before_delete:
- code: |
def function(collection, item: Model):
# do something here
pass
after_delete:
- code: |
def function(collection, data: dict):
# do something here
pass
transform_create_data:
- code: |
def function(collection, data: dict):
# do something here
return data
transform_update_data:
- code: |
def function(collection, data: dict):
# do something here
return data
transform_output_data:
- code: |
def function(collection, data: dict):
# do something here
return data
有关 mymodel.yaml
的模型规范的更多详细信息,请参阅 配置选项 中的 ModelSpec
。
客户端库
Aurelix 包括用于与 Aurelix 服务器交互的客户端库
from aurelix.client import Client
aurelix = Client('http://localhost:8000')
# create object
item = aurelix['mymodel'].create({'title': 'Title 1'})
# update object
item.update({'title': 'Title 2'})
# delete object
item.delete()
社区
加入我们吧:https://discord.gg/yuutKdD
Aurelix 的变更日志
0.1.2b8 (2023-10-20)
- 添加了 json 字段支持
0.1.2b7 (2023-10-16)
- 添加了非异步 sqlalchemy 存储类型(sqlalchemy-sync)。
- MSSQL 用户必须使用非异步存储类型
0.1.2b6 (2023-09-02)
- 添加了基于 yaml 的初始化模板中缺失的清单包含
0.1.2b5 (2023-08-27)
- 在配置中使用蛇形命名法
- 添加了简单的单元测试
0.1.2b4 (2023-08-26)
- 通过查询 userinfo 端点验证并解码 oidc 令牌,而不是盲目地信任它
- 删除 UserInfo 类,因为解码的令牌包含足够的身份信息
- 在模型响应中添加了关系对象
- 在客户端中添加了关系遍历
0.1.2b3 (2023-08-24)
- 添加了对对象上传的对象存储支持
- 添加了对象存储字段和工作流字段的字段编辑保护
0.1.2b2 (2023-08-23)
- 添加了字段和模型验证的钩子
- 允许在 CodeRefSpec 中指定函数名
- 添加了字段输入/输出转换钩子
- 添加了 alembic 支持
0.1.2.beta1 (2023-08-22)
- 修复了在 create/update/delete 事件中事件钩子未触发的问题
- 修复了 transform create/update/output 转换钩子未正确覆盖的问题
- 事件钩子和转换钩子现在是多项目和可链接的
- 修复了导致从 pip 安装失败的 MANIFEST.in
0.1.1 (2023-08-21)
- 添加了字段级别权限筛选器
- 添加了加密字符串字段
- 从响应对象中排除空值
- 修复了当未配置
swagger_ui_init_oauth
时的启动问题 - 添加了
init
命令行工具来初始化项目
0.1 (2023-08-21)
- 首次发布
项目详情
aurelix-0.1.2b8.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 3abdde45c098d815ff1e22e12821cbe259c32d2169c46ff6da1b40b98da3a910 |
|
MD5 | f76a2d8c4a31dd07621df11d675ca697 |
|
BLAKE2b-256 | 231628f6d4a61e577bc02453296c62227c8d288c49a950569c7f59a298790118 |