Optimize code generation data processing (#1020)

* Optimize code generation data processing

* Add SQL script generation

* Update code gen table scripts

* Update types

* Fix model jinja and type conversion
This commit is contained in:
Wu Clan
2026-01-20 18:27:42 +08:00
committed by GitHub
parent b2785dd46f
commit 1a6aba6105
22 changed files with 467 additions and 298 deletions
@@ -8,7 +8,7 @@ from backend.app.{{ app_name }}.model import {{ class_name }}
from backend.app.{{ app_name }}.schema.{{ table_name }} import Create{{ schema_name }}Param, Update{{ schema_name }}Param
class CRUD{{ class_name }}(CRUDPlus[{{ schema_name }}]):
class CRUD{{ class_name }}(CRUDPlus[{{ class_name }}]):
async def get(self, db: AsyncSession, pk: int) -> {{ class_name }} | None:
"""
获取{{ doc_comment }}
@@ -5,29 +5,48 @@
'HSTORE', 'INET', 'INT4MULTIRANGE', 'INT4RANGE', 'INT8MULTIRANGE', 'INT8RANGE', 'INTERVAL', 'JSONB', 'JSONPATH',
'MACADDR', 'MACADDR8', 'MONEY', 'NUMMULTIRANGE', 'NUMRANGE', 'OID', 'REGCLASS', 'REGCONFIG', 'TSMULTIRANGE', 'TSQUERY',
'TSRANGE', 'TSTZMULTIRANGE', 'TSTZRANGE', 'TSVECTOR'] %}
{% if default_datetime_column %}
from datetime import datetime
{% set FACTORY_TYPES = ['dict', 'list', 'list[str]', 'list[int]'] %}
{% set pd_types = models|map(attribute='pd_type')|list %}
{% set NEED_MYSQL_DIALECT = database_type == 'mysql' and model_types|select('in', MYSQL_TYPES)|list|length > 0 %}
{% set NEED_PGSQL_DIALECT = database_type == 'postgresql' and model_types|select('in', POSTGRESQL_TYPES)|list|length > 0 %}
{% set NEED_DATE = 'date' in pd_types %}
{% set NEED_DATETIME = datetime_mixin or 'datetime' in pd_types %}
{% set NEED_UNIVERSAL_TEXT = 'TEXT' in model_types or 'Text' in model_types or 'LONGTEXT' in model_types %}
{% set NEED_TIMEZONE = 'TIMESTAMP' in model_types or 'DateTime' in model_types or 'TIMESTAMP WITHOUT TIME ZONE' in model_types or 'TIMESTAMP WITH TIME ZONE' in model_types %}
{% if NEED_DATETIME or NEED_DATE %}
from datetime import {% if NEED_DATETIME %}datetime{% endif %}{% if NEED_DATE %}{% if NEED_DATETIME %}, {% endif %}date{% endif %}
{% endif %}
{% if model_types|select('in', DECIMAL_TYPES)|first %}
from decimal import Decimal
{% endif %}
{% if 'Uuid' in model_types or 'UUID' in model_types %}
from uuid import UUID
{% endif %}
{% endif %}
import sqlalchemy as sa
{% if database_type == 'mysql' -%}
{% if NEED_MYSQL_DIALECT %}
from sqlalchemy.dialects import mysql
{% else -%}
{% endif %}
{% if NEED_PGSQL_DIALECT %}
from sqlalchemy.dialects import postgresql
{% endif -%}
{% endif %}
from sqlalchemy.orm import Mapped, mapped_column
from backend.common.model import {% if default_datetime_column %}Base{% else %}DataClassBase{% endif %}, id_key
from backend.common.model import {% if datetime_mixin %}Base{% else %}DataClassBase{% endif %}, id_key
{%- if NEED_UNIVERSAL_TEXT or NEED_TIMEZONE %}, {% endif %}
{%- if NEED_UNIVERSAL_TEXT %}UniversalText{% endif %}
{%- if NEED_UNIVERSAL_TEXT and NEED_TIMEZONE %}, {% endif %}
{%- if NEED_TIMEZONE %}TimeZone{% endif %}
{% if NEED_TIMEZONE %}
from backend.utils.timezone import timezone
{% endif %}
class {{ class_name }}({% if default_datetime_column %}Base{% else %}DataClassBase{% endif %}):
class {{ class_name }}({% if datetime_mixin %}Base{% else %}DataClassBase{% endif %}):
"""{{ table_comment }}"""
__tablename__ = '{{ table_name }}'
@@ -38,41 +57,36 @@ class {{ class_name }}({% if default_datetime_column %}Base{% else %}DataClassBa
{%- if model.is_nullable %} Mapped[{{ model.pd_type }} | None]
{%- else %} Mapped[{{ model.pd_type }}]
{%- endif %} = mapped_column(
{%- if model.type in ['NVARCHAR', 'String', 'Unicode', 'VARCHAR'] -%}
{%- if model.type in ['TEXT', 'Text', 'LONGTEXT'] -%}
UniversalText
{%- elif model.type in ['TIMESTAMP', 'DateTime', 'TIMESTAMP WITHOUT TIME ZONE', 'TIMESTAMP WITH TIME ZONE'] -%}
TimeZone
{%- elif model.type in ['NVARCHAR', 'String', 'Unicode', 'VARCHAR', 'CHARACTER VARYING'] -%}
sa.String({{ model.length }})
{%- elif database_type == 'mysql' and model.type in MYSQL_TYPES -%}
mysql.{{ model.type }}()
mysql.{{ model.type|sqlalchemy_type }}()
{%- elif database_type == 'postgresql' and model.type in POSTGRESQL_TYPES -%}
{%- else -%}
sa.{{ model.type }}()
{%- endif -%}, default=
{%- if model.is_nullable and model.default == None -%}
None
{%- else -%}
{%- if model.default != None -%}
'{{ model.default }}'
{%- if model.type == 'ARRAY' -%}
postgresql.ARRAY(sa.String)
{%- else -%}
{%- if model.pd_type == 'str' -%}
''
{%- elif model.pd_type == 'int' -%}
0
{%- elif model.pd_type == 'bytes' -%}
b''
{%- elif model.pd_type == 'bool' -%}
True
{%- elif model.pd_type == 'float' -%}
0.0
{%- elif model.pd_type == 'dict' -%}
{}
{%- elif model.pd_type == 'date' or model.pd_type == 'datetime' -%}
timezone.now()
{%- elif model.pd_type == 'list[str]' -%}
()
{%- else -%}
''
{%- endif -%}
postgresql.{{ model.type|sqlalchemy_type }}()
{%- endif -%}
{%- endif -%}{% if model.sort != 0 %}, sort_order={{ model.sort }}{% endif %}, comment=
{%- else -%}
sa.{{ model.type|sqlalchemy_type }}()
{%- endif -%},
{%- if model.is_nullable and model.default == None %} default=None
{%- elif model.default != None %} default='{{ model.default }}'
{%- elif model.pd_type in FACTORY_TYPES %} default_factory={{ model.pd_type.split('[')[0] }}
{%- elif model.pd_type == 'str' %} default=''
{%- elif model.pd_type == 'int' %} default=0
{%- elif model.pd_type == 'bytes' %} default=b''
{%- elif model.pd_type == 'bool' %} default=True
{%- elif model.pd_type == 'float' %} default=0.0
{%- elif model.pd_type == 'date' %} default_factory=date.today
{%- elif model.pd_type == 'datetime' and model.type in ['TIMESTAMP', 'DateTime', 'TIMESTAMP WITHOUT TIME ZONE', 'TIMESTAMP WITH TIME ZONE'] %} default_factory=timezone.now
{%- elif model.pd_type == 'datetime' %} default_factory=datetime.now
{%- else %} default=None
{%- endif -%}, comment=
{%- if model.comment != None -%}
'{{ model.comment }}')
{% else -%}
@@ -1,5 +1,20 @@
{% if default_datetime_column %}
from datetime import datetime
{% set pd_types = models|map(attribute='pd_type')|list %}
{% set NEED_DATETIME = datetime_mixin or 'datetime' in pd_types %}
{% set NEED_DATE = 'date' in pd_types %}
{% set NEED_TIME = 'time' in pd_types %}
{% set NEED_TIMEDELTA = 'timedelta' in pd_types %}
{% set NEED_DECIMAL = 'Decimal' in pd_types %}
{% set NEED_UUID = 'UUID' in pd_types or 'str | UUID' in pd_types %}
{% if NEED_DATETIME or NEED_DATE or NEED_TIME or NEED_TIMEDELTA %}
from datetime import {% if NEED_DATETIME %}datetime{% endif %}{% if NEED_DATE %}{% if NEED_DATETIME %}, {% endif %}date{% endif %}{% if NEED_TIME %}{% if NEED_DATETIME or NEED_DATE %}, {% endif %}time{% endif %}{% if NEED_TIMEDELTA %}{% if NEED_DATETIME or NEED_DATE or NEED_TIME %}, {% endif %}timedelta{% endif %}
{% endif %}
{% if NEED_DECIMAL %}
from decimal import Decimal
{% endif %}
{% if NEED_UUID %}
from uuid import UUID
{% endif %}
from pydantic import ConfigDict, Field
@@ -35,7 +50,7 @@ class Get{{ schema_name }}Detail({{ schema_name }}SchemaBase):
model_config = ConfigDict(from_attributes=True)
id: int
{% if default_datetime_column %}
{% if datetime_mixin %}
created_time: datetime
updated_time: datetime | None = None
{% endif %}
@@ -0,0 +1,11 @@
insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values ('{{ doc_comment }}', '{{ schema_name }}', '/{{ app_name }}/{{ table_name|replace("_", "-") }}', 0, 'tabler:list', 1, '/{{ app_name }}/{{ table_name }}/views/index', null, 1, 1, 1, '', null, null, now(), null);
set @parent_menu_id = LAST_INSERT_ID();
insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values
('新增', 'Add{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:add', 1, 0, 1, '', null, @parent_menu_id, now(), null),
('修改', 'Edit{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:edit', 1, 0, 1, '', null, @parent_menu_id, now(), null),
('删除', 'Delete{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:del', 1, 0, 1, '', null, @parent_menu_id, now(), null),
('查询', 'Get{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:get', 1, 0, 1, '', null, @parent_menu_id, now(), null);
@@ -0,0 +1,9 @@
insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values ({{ parent_menu_id }}, '{{ doc_comment }}', '{{ schema_name }}', '/{{ app_name }}/{{ table_name|replace("_", "-") }}', 0, 'tabler:list', 1, '/{{ app_name }}/{{ table_name }}/views/index', null, 1, 1, 1, '', null, null, now(), null);
insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values
({{ button_ids[0] }}, '新增', 'Add{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:add', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[1] }}, '修改', 'Edit{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:edit', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[2] }}, '删除', 'Delete{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:del', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[3] }}, '查询', 'Get{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:get', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null);
@@ -0,0 +1,17 @@
do $$
declare
parent_menu_id bigint;
begin
insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values ('{{ doc_comment }}', '{{ schema_name }}', '/{{ app_name }}/{{ table_name|replace("_", "-") }}', 0, 'tabler:list', 1, '/{{ app_name }}/{{ table_name }}/views/index', null, 1, 1, 1, '', null, null, now(), null)
returning id into parent_menu_id;
insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values
('新增', 'Add{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:add', 1, 0, 1, '', null, parent_menu_id, now(), null),
('修改', 'Edit{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:edit', 1, 0, 1, '', null, parent_menu_id, now(), null),
('删除', 'Delete{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:del', 1, 0, 1, '', null, parent_menu_id, now(), null),
('查询', 'Get{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:get', 1, 0, 1, '', null, parent_menu_id, now(), null);
end $$;
select setval(pg_get_serial_sequence('sys_menu', 'id'),coalesce(max(id), 0) + 1, true) from sys_menu;
@@ -0,0 +1,9 @@
insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values ({{ parent_menu_id }}, '{{ doc_comment }}', '{{ schema_name }}', '/{{ app_name }}/{{ table_name|replace("_", "-") }}', 0, 'tabler:list', 1, '/{{ app_name }}/{{ table_name }}/views/index', null, 1, 1, 1, '', null, null, now(), null);
insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time)
values
({{ button_ids[0] }}, '新增', 'Add{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:add', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[1] }}, '修改', 'Edit{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:edit', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[2] }}, '删除', 'Delete{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:del', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null),
({{ button_ids[3] }}, '查询', 'Get{{ schema_name }}', null, 0, null, 2, null, '{{ permission }}:get', 1, 0, 1, '', null, {{ parent_menu_id }}, now(), null);