- 新增图像生成接口,支持试用、积分和自定义API Key模式 - 实现生成图片结果异步上传至MinIO存储,带重试机制 - 优化积分预扣除和异常退还逻辑,保障用户积分准确 - 添加获取生成历史记录接口,支持时间范围和分页 - 提供本地字典配置接口,支持模型、比例、提示模板和尺寸 - 实现图片批量上传接口,支持S3兼容对象存储 feat(admin): 增加管理员角色管理与权限分配接口 - 实现角色列表查询、角色创建、更新及删除功能 - 增加权限列表查询接口 - 实现用户角色分配接口,便于统一管理用户权限 - 增加系统字典增删查改接口,支持分类过滤和排序 - 权限控制全面覆盖管理接口,保证安全访问 feat(auth): 完善用户登录注册及权限相关接口与页面 - 实现手机号验证码发送及校验功能,保障注册安全 - 支持手机号注册、登录及退出接口,集成日志记录 - 增加修改密码功能,验证原密码后更新 - 提供动态导航菜单接口,基于权限展示不同菜单 - 实现管理界面路由及日志、角色、字典管理页面访问权限控制 - 添加系统日志查询接口,支持关键词和等级筛选 feat(app): 初始化Flask应用并配置蓝图与数据库 - 创建应用程序工厂,加载配置,初始化数据库和Redis客户端 - 注册认证、API及管理员蓝图,整合路由 - 根路由渲染主页模板 - 应用上下文中自动创建数据库表,保证运行环境准备完毕 feat(database): 提供数据库创建与迁移支持脚本 - 新增数据库创建脚本,支持自动检测是否已存在 - 添加数据库表初始化脚本,支持创建和删除所有表 - 实现RBAC权限初始化,包含基础权限和角色创建 - 新增字段手动修复脚本,添加用户API Key和积分字段 - 强制迁移脚本支持清理连接和修复表结构,初始化默认数据及角色分配 feat(config): 新增系统配置参数 - 配置数据库、Redis、Session和MinIO相关参数 - 添加AI接口地址及试用Key配置 - 集成阿里云短信服务配置及开发模式相关参数 feat(extensions): 初始化数据库、Redis和MinIO客户端 - 创建全局SQLAlchemy数据库实例和Redis客户端 - 配置基于boto3的MinIO兼容S3客户端 chore(logs): 添加示例系统日志文件 - 记录用户请求、验证码发送成功与失败的日志信息
135 lines
4.7 KiB
Python
135 lines
4.7 KiB
Python
"""When it comes to combining multiple controller or view functions
|
|
(however you want to call them) you need a dispatcher. A simple way
|
|
would be applying regular expression tests on the ``PATH_INFO`` and
|
|
calling registered callback functions that return the value then.
|
|
|
|
This module implements a much more powerful system than simple regular
|
|
expression matching because it can also convert values in the URLs and
|
|
build URLs.
|
|
|
|
Here a simple example that creates a URL map for an application with
|
|
two subdomains (www and kb) and some URL rules:
|
|
|
|
.. code-block:: python
|
|
|
|
m = Map([
|
|
# Static URLs
|
|
Rule('/', endpoint='static/index'),
|
|
Rule('/about', endpoint='static/about'),
|
|
Rule('/help', endpoint='static/help'),
|
|
# Knowledge Base
|
|
Subdomain('kb', [
|
|
Rule('/', endpoint='kb/index'),
|
|
Rule('/browse/', endpoint='kb/browse'),
|
|
Rule('/browse/<int:id>/', endpoint='kb/browse'),
|
|
Rule('/browse/<int:id>/<int:page>', endpoint='kb/browse')
|
|
])
|
|
], default_subdomain='www')
|
|
|
|
If the application doesn't use subdomains it's perfectly fine to not set
|
|
the default subdomain and not use the `Subdomain` rule factory. The
|
|
endpoint in the rules can be anything, for example import paths or
|
|
unique identifiers. The WSGI application can use those endpoints to get the
|
|
handler for that URL. It doesn't have to be a string at all but it's
|
|
recommended.
|
|
|
|
Now it's possible to create a URL adapter for one of the subdomains and
|
|
build URLs:
|
|
|
|
.. code-block:: python
|
|
|
|
c = m.bind('example.com')
|
|
|
|
c.build("kb/browse", dict(id=42))
|
|
'http://kb.example.com/browse/42/'
|
|
|
|
c.build("kb/browse", dict())
|
|
'http://kb.example.com/browse/'
|
|
|
|
c.build("kb/browse", dict(id=42, page=3))
|
|
'http://kb.example.com/browse/42/3'
|
|
|
|
c.build("static/about")
|
|
'/about'
|
|
|
|
c.build("static/index", force_external=True)
|
|
'http://www.example.com/'
|
|
|
|
c = m.bind('example.com', subdomain='kb')
|
|
|
|
c.build("static/about")
|
|
'http://www.example.com/about'
|
|
|
|
The first argument to bind is the server name *without* the subdomain.
|
|
Per default it will assume that the script is mounted on the root, but
|
|
often that's not the case so you can provide the real mount point as
|
|
second argument:
|
|
|
|
.. code-block:: python
|
|
|
|
c = m.bind('example.com', '/applications/example')
|
|
|
|
The third argument can be the subdomain, if not given the default
|
|
subdomain is used. For more details about binding have a look at the
|
|
documentation of the `MapAdapter`.
|
|
|
|
And here is how you can match URLs:
|
|
|
|
.. code-block:: python
|
|
|
|
c = m.bind('example.com')
|
|
|
|
c.match("/")
|
|
('static/index', {})
|
|
|
|
c.match("/about")
|
|
('static/about', {})
|
|
|
|
c = m.bind('example.com', '/', 'kb')
|
|
|
|
c.match("/")
|
|
('kb/index', {})
|
|
|
|
c.match("/browse/42/23")
|
|
('kb/browse', {'id': 42, 'page': 23})
|
|
|
|
If matching fails you get a ``NotFound`` exception, if the rule thinks
|
|
it's a good idea to redirect (for example because the URL was defined
|
|
to have a slash at the end but the request was missing that slash) it
|
|
will raise a ``RequestRedirect`` exception. Both are subclasses of
|
|
``HTTPException`` so you can use those errors as responses in the
|
|
application.
|
|
|
|
If matching succeeded but the URL rule was incompatible to the given
|
|
method (for example there were only rules for ``GET`` and ``HEAD`` but
|
|
routing tried to match a ``POST`` request) a ``MethodNotAllowed``
|
|
exception is raised.
|
|
"""
|
|
|
|
from .converters import AnyConverter as AnyConverter
|
|
from .converters import BaseConverter as BaseConverter
|
|
from .converters import FloatConverter as FloatConverter
|
|
from .converters import IntegerConverter as IntegerConverter
|
|
from .converters import PathConverter as PathConverter
|
|
from .converters import UnicodeConverter as UnicodeConverter
|
|
from .converters import UUIDConverter as UUIDConverter
|
|
from .converters import ValidationError as ValidationError
|
|
from .exceptions import BuildError as BuildError
|
|
from .exceptions import NoMatch as NoMatch
|
|
from .exceptions import RequestAliasRedirect as RequestAliasRedirect
|
|
from .exceptions import RequestPath as RequestPath
|
|
from .exceptions import RequestRedirect as RequestRedirect
|
|
from .exceptions import RoutingException as RoutingException
|
|
from .exceptions import WebsocketMismatch as WebsocketMismatch
|
|
from .map import Map as Map
|
|
from .map import MapAdapter as MapAdapter
|
|
from .matcher import StateMachineMatcher as StateMachineMatcher
|
|
from .rules import EndpointPrefix as EndpointPrefix
|
|
from .rules import parse_converter_args as parse_converter_args
|
|
from .rules import Rule as Rule
|
|
from .rules import RuleFactory as RuleFactory
|
|
from .rules import RuleTemplate as RuleTemplate
|
|
from .rules import RuleTemplateFactory as RuleTemplateFactory
|
|
from .rules import Subdomain as Subdomain
|
|
from .rules import Submount as Submount
|