mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-20 20:39:55 +00:00
feat(dependencies): update asyncmy and pandas versions for improved performance and compatibility
- Upgraded asyncmy from version 0.2.9 to 0.2.11 to leverage enhancements and bug fixes. - Updated pandas from version 2.2.2 to 2.2.3 for better data processing capabilities. - Added a new configuration option LOGIN_RESOLVE_IP_LOCATION to control IP location resolution during login. - Enhanced login service to handle IP location resolution based on the new configuration. - Improved validation logic in menu request handling to ensure proper redirection address for specific menu types. - Adjusted CRUD template generation to dynamically use primary key column names for better flexibility. - Updated Vue components to ensure proper handling of dynamic primary key references in menu items and forms.
This commit is contained in:
@@ -111,7 +111,7 @@ class {{ class_name }}CRUD(CRUDBase[{{ class_name }}Model, {{ class_name }}Creat
|
||||
返回:
|
||||
- Dict: 分页数据
|
||||
"""
|
||||
order_by_list = order_by or [{'id': 'asc'}]
|
||||
order_by_list = order_by or [{'{{ pk_column_name }}': 'asc'}]
|
||||
search_dict = search or {}
|
||||
return await self.page(
|
||||
offset=offset,
|
||||
|
||||
@@ -17,7 +17,7 @@ class {{ class_name }}CreateSchema(BaseModel):
|
||||
{{ function_name }}新增模型
|
||||
"""
|
||||
{% for column in columns %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{% if column.column_name == 'status' %}
|
||||
{{ column.column_name }}: {{ column.python_type }} = Field(default="0", description='{{ column.column_comment }}')
|
||||
{% elif column.column_name == 'description' %}
|
||||
|
||||
@@ -74,7 +74,7 @@ class {{ class_name }}Service:
|
||||
- dict - 分页查询结果
|
||||
"""
|
||||
search_dict = search.__dict__ if search else {}
|
||||
order_by_list = order_by or [{'id': 'asc'}]
|
||||
order_by_list = order_by or [{'{{ pk_column_name }}': 'asc'}]
|
||||
offset = (page_no - 1) * page_size
|
||||
result = await {{ class_name }}CRUD(auth).page_{{ business_name }}_crud(
|
||||
offset=offset,
|
||||
@@ -128,7 +128,7 @@ class {{ class_name }}Service:
|
||||
{% for column in columns %}
|
||||
{% if column.is_unique == '1' %}
|
||||
exist_obj = await {{ class_name }}CRUD(auth).get({{ column.column_name }}=data.{{ column.column_name }})
|
||||
if exist_obj and exist_obj.id != id:
|
||||
if exist_obj and getattr(exist_obj, '{{ pk_column_name }}') != id:
|
||||
raise CustomException(msg='更新失败,{{ column.column_comment }}重复')
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -271,7 +271,7 @@ class {{ class_name }}Service:
|
||||
exists_obj = await {{ class_name }}CRUD(auth).get({{ column.column_name }}=create_schema.{{ column.column_name }})
|
||||
if exists_obj:
|
||||
if update_support:
|
||||
await {{ class_name }}CRUD(auth).update(id=exists_obj.id, data=create_schema)
|
||||
await {{ class_name }}CRUD(auth).update(id=getattr(exists_obj, '{{ pk_column_name }}'), data=create_schema)
|
||||
success_count += 1
|
||||
else:
|
||||
error_msgs.append(f"第{count}行: {{ column.column_comment }} {create_schema.{{ column.column_name }}} 已存在")
|
||||
|
||||
@@ -110,8 +110,11 @@ export interface {{ class_name }}PageQuery extends PageQuery {
|
||||
|
||||
// 列表展示项
|
||||
export interface {{ class_name }}Table extends BaseType {
|
||||
{% if pk_column_name != 'id' and pk_column %}
|
||||
{{ pk_column_name }}?: {{ pk_column.python_type | python_to_ts_type }};
|
||||
{% endif %}
|
||||
{% for column in columns %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time'] %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time'] and column.column_name != pk_column_name %}
|
||||
{{ column.column_name }}?: {{ column.python_type | python_to_ts_type }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -121,8 +124,11 @@ export interface {{ class_name }}Table extends BaseType {
|
||||
|
||||
// 新增/修改/详情表单参数
|
||||
export interface {{ class_name }}Form extends BaseFormType {
|
||||
{% if pk_column_name != 'id' and pk_column %}
|
||||
{{ pk_column_name }}?: {{ pk_column.python_type | python_to_ts_type }};
|
||||
{% endif %}
|
||||
{% for column in columns %}
|
||||
{% if (column.is_insert or column.is_edit) and column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if (column.is_insert or column.is_edit) and column.column_name not in ['uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{{ column.column_name }}?: {{ column.python_type | python_to_ts_type }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
size="small"
|
||||
link
|
||||
icon="View"
|
||||
@click="handleOpenDialog('detail', scope.row.id)"
|
||||
@click="handleOpenDialog('detail', scope.row['{{ pk_column_name }}'])"
|
||||
>
|
||||
详情
|
||||
</el-button>
|
||||
@@ -138,7 +138,7 @@
|
||||
size="small"
|
||||
link
|
||||
icon="Edit"
|
||||
@click="handleOpenDialog('update', scope.row.id)"
|
||||
@click="handleOpenDialog('update', scope.row['{{ pk_column_name }}'])"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
@@ -148,7 +148,7 @@
|
||||
size="small"
|
||||
link
|
||||
icon="Delete"
|
||||
@click="handleRowDelete(scope.row.id)"
|
||||
@click="handleRowDelete(scope.row['{{ pk_column_name }}'])"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
@@ -210,7 +210,7 @@
|
||||
{% set parentheseIndex = column_comment.find("(") %}
|
||||
{% set comment = column_comment[:parentheseIndex] if parentheseIndex != -1 else column_comment %}
|
||||
{% set required = 'true' if not column.is_nullable else 'false' %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{% if column.column_name == "status" %}
|
||||
<el-form-item label="状态" prop="status" :required="true">
|
||||
<el-radio-group v-model="formData.status">
|
||||
@@ -321,6 +321,9 @@ import SingleImageUpload from "@/components/Upload/SingleImageUpload.vue";
|
||||
|
||||
const { searchRef, contentRef, handleQueryClick, handleResetClick, refreshList } = useCrudList();
|
||||
|
||||
/** 数据表主键字段名(与导入表结构一致,避免非 id 主键时操作错行) */
|
||||
const PK = "{{ pk_column_name }}" as const;
|
||||
|
||||
function triggerUserSearch() {
|
||||
nextTick(() => refreshList());
|
||||
}
|
||||
@@ -523,7 +526,7 @@ const detailFormData = ref<{{ class_name }}Table>({});
|
||||
const formData = reactive<{{ class_name }}Form>({
|
||||
{% for column in columns %}
|
||||
{% if column.is_insert or column.is_edit %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{{ column.column_name }}: undefined,
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -539,7 +542,7 @@ const dialogVisible = reactive({
|
||||
const rules = reactive({
|
||||
{% for column in columns %}
|
||||
{% if column.is_insert or column.is_edit %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{{ column.column_name }}: [{ required: {% if not column.is_nullable %}true{% else %}false{% endif %}, message: "请填写{{ column.column_comment or column.column_name }}", trigger: "blur" }],
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -568,7 +571,7 @@ function handleRowDelete(id: number) {
|
||||
const initialFormData: {{ class_name }}Form = {
|
||||
{% for column in columns %}
|
||||
{% if column.is_insert or column.is_edit %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
{{ column.column_name }}: undefined,
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -603,7 +606,7 @@ async function handleOpenDialog(type: "create" | "update" | "detail", id?: numbe
|
||||
dialogVisible.title = "新增{{ function_name }}";
|
||||
{% for column in columns %}
|
||||
{% if column.is_insert or column.is_edit %}
|
||||
{% if column.column_name not in ['id', 'uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] %}
|
||||
{% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %}
|
||||
formData.{{ column.column_name }} = undefined;
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -616,10 +619,10 @@ async function handleSubmit() {
|
||||
dataFormRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
const submitData = { ...formData };
|
||||
const id = formData.id;
|
||||
const id = formData[PK] as number | undefined;
|
||||
try {
|
||||
if (id) {
|
||||
await {{ class_name }}API.update{{ class_name }}(id, { id, ...submitData });
|
||||
await {{ class_name }}API.update{{ class_name }}(id, { ...submitData, [PK]: id });
|
||||
} else {
|
||||
await {{ class_name }}API.create{{ class_name }}(submitData);
|
||||
}
|
||||
@@ -635,7 +638,7 @@ async function handleSubmit() {
|
||||
|
||||
async function handleMoreClick(status: string) {
|
||||
const rows = contentRef.value?.getSelectionData() ?? [];
|
||||
const ids = rows.map((r: { id?: number }) => r.id).filter(Boolean) as number[];
|
||||
const ids = rows.map((r: Record<string, number | undefined>) => r[PK]).filter(Boolean) as number[];
|
||||
if (!ids.length) return;
|
||||
ElMessageBox.confirm(`确认${status === "0" ? "启用" : "停用"}该项数据?`, "警告", {
|
||||
confirmButtonText: "确定",
|
||||
|
||||
@@ -161,7 +161,11 @@ class Jinja2TemplateUtil:
|
||||
"parent_list_rel_name": "",
|
||||
"parent_table_name": "",
|
||||
"parent_model_class_name": "",
|
||||
"parent_pk_column_name": "id",
|
||||
# 数据表实际主键列名(用于生成前端行键等;ModelMixin 仍默认带 id 字段)
|
||||
"pk_column_name": (gen_table.pk_column.column_name if gen_table.pk_column else None)
|
||||
or "id",
|
||||
"parent_pk_column_name": (gen_table.pk_column.column_name if gen_table.pk_column else None)
|
||||
or "id",
|
||||
"sub_table_fk_name": "",
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user