自定义字段/动态字段的实现方法汇总
参考1-1:一个程序猿(1/2)
自定义字段自动添加及保存到数据库
https://www.bilibili.com/video/BV1mP411Q7xn/?vd_source=f0135f6d3fa76fb816f47132eda5df66
原文概述:
自定义字段自动添加及保存到数据库
应大家要求,讲解下自定义字段动态添加到数据库的实现原理。主要包括以下3个逻辑。
1、定义业务对象,业务对象与数据库表关联
2、定义当前业务对象的自定义字段,并同步到当前业务对象的数据库表上
- 管理界面和制单界面自动显示当前自定义字段
- 制单界面填写数据后能够将自定义字段数值保存到数据库
- 管理界面自动显示编辑后的自定义字段数值
- 编辑表单时自动将自定义字段值内容显示到当前界面
Note:
用户增加自定义字段后,后端执行了add字段到对应数据表的代码。
数据列表显示自定义字段时,后端先查找当前表有哪些自定义字段,然后读取对应的值,然后用push方法添加到当前显示的数据表。
摘要
本视频是关于动态添加自定义字段实现原理系列的第一部分,主要讲解了如何定义业务对象的自定义字段并将其同步到数据库表,以及如何在管理界面和制单界面自动显示这些自定义字段。视频通过一个采购申请的实例,详细演示了自定义字段的添加、数据库插入逻辑,以及前端界面如何动态加载和显示这些字段,为后续的数据填写和更新功能打下了基础。
亮点
- 📝 系统支持自定义字段的定义,这些字段会与业务对象关联并自动同步到对应的数据库表中,实现了字段的动态扩展。
- 🛠️ 详细讲解了自定义字段插入数据库的逻辑,包括根据字段类型(文本、数字、日期、列表)选择合适的数据库字段类型,并通过SQL命令动态添加表列。
- 🖥️ 演示了在管理界面和制单界面上,自定义字段是如何自动显示出来的,这是通过前端JS方法动态获取业务对象的自定义字段列表并渲染到页面实现的。
- 🛒 以采购申请为例,具体展示了如何为表头和分录添加自定义字段,并观察到这些字段是如何实时反映在数据库和前端界面的。
- ⏱️ 强调了前端加载自定义字段时存在一个加载顺序和延迟,即固定字段先加载,自定义字段随后动态加载出来。
#自定义字段 #动态添加 #数据库同步 #前端渲染 #业务对象
思考
- 观众如何才能实现像视频中那样,将自定义字段动态地插入到数据库表中?
- 视频中提到了后台代码中的 smoking customer field control 方法,特别是 cs insert 和 add table and column 方法。这些方法会根据自定义字段的类型(文本、数字、日期等)动态构建SQL命令,将新的列添加到对应的数据库表中。开发者需要实现类似的功能,通过编程方式在运行时修改数据库表结构。
- 为什么在制单页面(如新增采购申请)上,自定义字段的加载会有一个延迟?
- 视频中解释道,这是因为前端加载流程包括了先执行页面固有的JS方法,然后再执行混合的自定义JS方法。自定义字段是在混合JS方法中动态获取并渲染的,因此会出现先加载固定字段,再加载自定义字段的先后顺序和视觉上的延迟。
术语解释
- 业务对象(Object Code): 在系统中代表一个具体的业务实体或模块,如“采购申请”。自定义字段会与这些业务对象关联,从而实现对特定业务数据的扩展。
- 自定义字段(Custom Field): 用户根据业务需求自行定义的数据字段,区别于系统预设的固定字段。这些字段可以动态添加到业务对象的数据库表和前端界面。
- 数据库同步(Database Synchronization): 指在定义自定义字段后,系统自动将其对应的列添加到后台数据库表中,确保数据存储结构与前端定义保持一致的过程。
- 前端渲染(Frontend Rendering): 指浏览器通过执行JavaScript代码,动态获取自定义字段信息,并将其显示在管理界面、制单界面等用户界面的过程。
- 混合JS方法(Mixed JS Method): 视频中提到的一种前端实现方式,可能指的是系统自带的通用JS方法与为实现自定义字段功能而扩展的特定JS方法的结合使用。
参考1-2:一个程序猿(2/2)
自定义字段自动添加及保存到数据库
https://www.bilibili.com/video/BV1iN41117fs
摘要
本视频详细讲解了自定义字段的动态添加实现原理,主要围绕如何将自定义字段的数据保存到数据库、如何在前端页面进行展示以及更新。作者以采购申请为例,演示了自定义字段(如“冰蛋”、“冰墩站”等)的保存过程,并深入剖析了前端数据提交、后端逻辑处理(包括使用Map而非系统自带的VO进行数据映射)以及数据回显的实现细节。核心在于前端提交数据时需将自定义字段整理进Form Data或Map,后端接收后进行解析,并在前端展示时动态地将这些字段的值注入到返回的结果集中。
亮点
- 💾 数据保存策略:前端在提交表单时,需要将自定义字段信息整理并放入model或map中,而非依赖系统自带的VO对象,确保自定义字段能被正确传递到后端。
- 🗺️ 后端数据映射:后端接收数据时,不能直接使用系统自带的VO配置,而应使用Map来接收所有数据,防止自定义字段在映射过程中丢失。
- 🔄 Map到Class转换:后端通过自定义的map to class方法,将Map中包含的固定字段和自定义字段分别映射到对应的实体类和单独的数据集中。
- 🚀 字段值动态回显:为了在前端管理列表和单据详情页面正确显示自定义字段,系统利用AOP切面技术,在数据返回前端时动态判断业务对象是否包含自定义字段注解,并将其值注入到返回结果集中。
- 💡 前端显示逻辑:前端管理界面和单据界面的自定义字段显示不需要额外赋值,只要后台返回的结果集中包含这些列的数据,前端控件就能根据data code或key自动匹配并显示。
#自定义字段 #动态添加 #数据保存 #前端显示 #后端逻辑
思考
- 为什么在前端提交数据时,不能使用系统自带的VO,而需要用Map或手动整理数据?
- Answer: 系统自带的VO(Value Object)通常只包含预定义的固定字段。如果使用它来提交数据,自定义字段的信息在序列化或映射过程中容易丢失。使用Map或手动将自定义字段数据整理到Form Data中,可以确保所有自定义字段都能随同其他数据一起被正确提交到后端。
- 后端如何处理前端传递过来的包含自定义字段的数据,以防止数据丢失?
- Answer: 后端应避免直接将前端数据映射到系统生成的标准实体类,而应使用Map来接收所有数据。之后,通过自定义的map to class方法,将Map中的固定字段映射到对应的实体类,并将自定义字段单独提取并保存,确保所有数据都被有效处理。
术语解释
- 自定义字段 (Custom Fields): 指用户根据业务需求,在系统原有固定字段之外自行定义的数据字段,例如视频中提到的“冰蛋”、“冰墩站”等。
- VO (Value Object): 值对象,通常指在系统设计中,用于在不同层之间传递数据的一种简单Java对象,只包含数据属性和对应的getter/setter方法。
- Form Data: 表单数据,指前端HTML表单提交时,将表单控件的值组织成键值对的形式,用于HTTP请求体传输的数据格式。
- AOP (Aspect-Oriented Programming): 面向切面编程,一种编程范式,旨在通过在程序运行期间动态地“切入”到代码的特定点来添加额外功能(如日志、安全、事务管理等),而无需修改原有业务逻辑代码。视频中用于在数据返回前端时动态注入自定义字段值。
- Map to Class: 一种数据转换机制,指将Map结构的数据(通常为键值对形式)映射或转换成一个具体类的实例对象,将Map的键与类的属性进行匹配并赋值。
参考2:博客园-edda_huang
https://www.cnblogs.com/edda/p/14419839.html
这篇博客核心介绍了 CRM 系统中自定义字段的设计与实现方案,用于解决不同行业 / 业态客户信息 “通用属性固定、个性化属性差异大” 的问题,同时对比了 EAV 模型并给出优化方向,具体可总结为 4 个核心部分:
一、核心需求:为什么需要自定义字段?
CRM 系统的 “客户信息表(T_CUSTOM)” 中,姓名、电话等基础属性是通用的,但不同行业需要个性化属性:
- 医疗行业:需记录客户体重、血压;
- 运输行业:需记录货物品类、产量;
- 快消行业:需记录客户爱好、年龄、星座。传统固定表结构(新增字段需改表)无法适配这种差异,因此需要 “自定义字段” 实现灵活扩展,让不同行业按需添加属性。
二、方案设计:3 张核心表 + JSON 存储自定义模板
通过 3 张数据库表联动,用 JSON 格式存储自定义字段模板,实现 “不同业态对应不同模板”:
- 自定义模板表(T_CUSTOM_FIELD_TEMPLATE)存储自定义字段的配置模板,以 JSON 格式记录字段详情(如字段标签、名称、类型、约束等)。示例模板(运输行业):包含 “货品名称(文本框,必填)”“产量(数字框,必填,精度 2 位)”“爱好(下拉框,选项为看书 / 羽毛球)” 等字段,明确每个字段的类型、默认值、校验规则。
- 客户信息表(T_CUSTOM)存储客户通用属性(姓名、电话等),同时用大文本字段存储该客户所属行业的 “自定义模板关联信息”,关联到对应的自定义模板。
- 业态 - 模板关联表(T_BUSINISS_TEMPLATE)建立 “行业 / 业态” 与 “自定义模板” 的对应关系,比如 “运输行业” 绑定运输相关的自定义模板,“医疗行业” 绑定医疗相关模板,确保新增客户时能自动匹配对应模板。
三、实现逻辑:前后端如何联动加载 / 保存自定义字段?
1. 后端:统一处理自定义字段的新增与模板存储
- 新增自定义字段时,通过代码获取前端传参,拼装成包含字段类型、约束、默认值的 JSON 字符串;
- 将 JSON 模板存入T_CUSTOM_FIELD_TEMPLATE,并通过T_BUSINISS_TEMPLATE关联到对应业态;
- 新增客户时,根据客户所属业态,从关联表中找到对应的模板,传递给前端。
2. 前端:动态加载模板生成自定义字段界面
- 后端将 JSON 模板通过request传递到前端,前端解析 JSON 数据;
- 通过 JS 循环判断字段类型(文本框、数字框、日期框、下拉框),动态拼接 HTML 代码(如文本框用easyui-textbox,下拉框用easyui-combobox);
- 将拼接好的 HTML 插入页面指定区域(如customFieldDiv),实现 “不同业态加载不同自定义字段界面”(如医疗行业显示体重输入框,运输行业显示产量输入框)。
四、优化方向与补充说明
- 数据库优化原方案用longtext存储 JSON 模板,可升级为 MySQL 5.7 + 的json类型,更便于字段查询和解析;同时可参考 Hibernate 映射 JSON 字段的方案,优化 ORM 层适配。
- 功能扩展现有自定义字段类型仅支持文本框、数字框、日期框、单选 / 多选框,可进一步扩展图片、音频、视频等类型,覆盖更多场景。
- 对比 EAV 模型该方案是 “模板化 JSON 存储”,与之前提到的 EAV(实体 - 属性 - 值)模型是两种不同的自定义字段解决方案,EAV 通过多表关联存储属性值,可自行百度对比适用场景。
- 潜在挑战当自定义字段数量过多时,页面布局的美观性和用户操作体验会下降,需额外设计布局方案(如分栏、折叠等)。
EAV模型(Entity-Attribute-Value,实体-属性-值)是一种灵活的数据库设计模式,专门用于处理具有动态、可变属性的数据场景1
3
6
EAV模型的基本概念
EAV模型通过三个核心表来组织数据:
1. 实体表(Entity Table) 存储实体的基本信息,如产品ID、名称等,每个实体具有唯一的标识符
2. 属性表(Attribute Table) 定义所有可能的属性及其元数据,包括属性名称、数据类型等信息
3. 值表(Value Table) 存储每个实体的具体属性值,通过实体ID和属性ID进行关联
EAV模型的核心优势
灵活性极高 :可以动态地添加、修改或删除属性,而无需修改数据库表结构
存储效率 :避免传统宽表中大量空值造成的存储空间浪费,特别适合稀疏数据场景
扩展性强 :支持存储不同实体的多样化属性,适应业务需求的快速变化
方法总结
1、EAV模型(用Django-EVA2包实现)
将实体、属性和值分别存储在三个不同的表中,查询数据时再将三个值连接起来。
优点:灵活度极高、稀疏数据存储高效、属性即数据
缺点:查询复杂,效率低下、数据完整性难以保证(值统一存储为字符串类型)、索引设计复杂、理解和管理成本高、需要三张表
2、序列化存储
(如参考2):将动态字段序列化成 JSON/XML 字符串存入一个 TEXT 字段。查询困难,通常只在不需要根据这些字段进行搜索和过滤时使用。
优点:灵活度极高、查询复杂度中低、数据完整性较好、性能较好、开发复杂度低、只需一张表
3、半结构化数据存储(NoSQL)
使用 MongoDB、PostgreSQL 的 JSONB 等。它们原生支持动态字段,查询性能比 EAV 好得多,是现代应用的首选。
4、预分配“宽表”
预留一些备用列(如 custom_field_1 到 custom_field_20)。灵活性有限,但实现简单。
5、原生JSON存储(推荐)
数据库提供原生的JSON或JSONB数据类型,能够理解并优化JSON数据的存储与查询
具体场景推荐
- 传统序列化存储
- 老旧系统改造
- 简单的配置存储
- 不需要查询的动态数据
- 原生JSON存储 ⭐ 推荐大多数场景
- 已有关系数据库,需要添加灵活字段
- 混合模式:固定字段+动态字段
- 需要SQL的强大查询能力
- PostgreSQL的JSONB是最佳选择
- 专门的半结构化数据库
- 全新项目,数据结构高度不确定
- 大规模、高性能需求
- 开发团队熟悉NoSQL
- MongoDB是典型代表
问:支持原生JSON存储的数据库
主流数据库都支持,包括PostgreSQL、MySQL、MongoDB、SQLite、StarRocks、Kingbase
问:自定义字段怎么存储图片或视频
存储文件路径/URL,不存储图片或视频本身的二进制数据。
问:半结构化数据存储(NoSQL)和序列化存储、原生Json存储方法有什么不同
| 方法 | 存储形式 | 数据库支持 查询内部字段 | 索引支持 | 典型数据库 |
| 序列化存储 | 字符串 | 否 | 否 | 任何数据库(如MySQL的TEXT字段) |
| 原生JSON存储 | JSON类型 | 是 | 是 | PostgreSQL(JSONB)、MySQL(JSON) |
| NoSQL存储 | 文档 | 是 | 是 | MongoDB |
实际上,这三种方法不是并列关系,而是包含和演进关系:
序列化存储 (广义概念)
↓
原生JSON存储 (现代实现方式)
↓
半结构化数据存储 (更广泛的架构模式,包含原生JSON存储)
实战:Django实现自定义字段的CRUD(增删查改)
方法1:使用Django原生支持的JSONFieds存储


SQLite中的数据记录:
sqlite> select * from truck_system_truck;
1|1563|金龙|16+1|{"\u63d0\u6210": "30", "\u5916\u8c03\u9a7e\u9a76\u5458\u5de5\u8d44": "200"}|2025-10-30 09:08:06.066708
2|1567|22|33|{"\u63d0\u6210": "20", "\u5916\u8c03\u9a7e\u9a76\u5458\u5de5\u8d44": "300"}|2025-10-30 09:14:49.983720
自定义字段功能实现总结
核心设计原理
- 数据库模型设计
- CustomField模型 :定义自定义字段的元数据(名称、类型、可见性)
- Truck模型 :包含基础字段 + JSONField用于存储自定义字段值
- JSON存储优势 :灵活扩展,无需修改数据库结构
- 动态表单机制
- TruckForm类 :在运行时根据CustomField配置动态生成表单字段
- 字段命名规则 : custom_字段名 避免与基础字段冲突
- 初始值设置 :编辑时从JSON字段读取并填充表单
- Admin后台集成
- 简化配置 :避免复杂的fieldsets,让表单处理字段显示
- 动态字段管理 :通过重写get_form和get_fields方法
完整代码实现
models.py 关键代码:
class CustomField(models.Model):
name = models.CharField(max_length=100)
field_type = models.CharField(max_length=20)
is_visible = models.BooleanField(default=True)
class Truck(models.Model):
plate_number = models.CharField(max_length=20)
brand = models.CharField(max_length=50)
model = models.CharField(max_length=50)
custom_data = models.JSONField(default=dict, blank=True)
def get_custom_value(self, field_name):
return self.custom_data.get(field_name, '')
def set_custom_value(self, field_name, value):
self.custom_data[field_name] = value
self.save()
admin.py 关键代码:
class TruckForm(forms.ModelForm):
class Meta:
model = Truck
fields = ['plate_number', 'brand', 'model']
def __init__(self, *args, **kwargs):
# 调用父方法获取固定字段
super().__init__(*args, **kwargs)
# 动态添加自定义字段,
#只要把自定义字段遍历添加到self.fields字段中,Django后台就会自动渲染显示出所有字段(包括固定字段和自定义字段)
for field in CustomField.objects.filter(is_visible=True):
field_name = f"custom_{field.name}"
self.fields[field_name] = forms.CharField(required=False)
if self.instance.pk:
self.fields[field_name].initial = self.instance.get_custom_value(field.name)
def save(self, commit=True):
truck = super().save(commit=False)
# 先设置自定义字段值
for field in CustomField.objects.filter(is_visible=True):
field_name = f"custom_{field.name}"
if field_name in self.cleaned_data:
truck.set_custom_value(field.name, self.cleaned_data[field_name])
# 再保存整个对象
if commit:
truck.save()
return truck
class TruckAdmin(admin.ModelAdmin):
form = TruckForm
fields = ['plate_number', 'brand', 'model'] # 基础字段
实现步骤总结
- 创建模型 :定义CustomField和主模型(含JSONField)
- 实现表单 :创建动态表单类处理自定义字段
- 配置Admin :使用自定义表单,简化字段配置
- 数据迁移 :生成并执行迁移文件
- 功能测试 :在Admin后台验证功能
重要注意事项
- 字段命名规范
- 自定义字段使用 custom_ 前缀避免冲突
- JSON存储使用原始字段名作为键
- 保存顺序关键
- 必须先设置自定义字段值,再保存对象
- 避免在保存后修改JSON字段导致数据丢失
- Admin配置简化
- 不要使用复杂的fieldsets
- 让表单类完全负责字段显示逻辑
- 重写get_form确保使用自定义表单
- 错误处理
- 处理CustomField查询可能为空的情况
- 确保cleaned_data中存在字段再访问
扩展建议
- 字段类型支持
- 可以扩展支持数字、日期、选择框等字段类型
- 在CustomField中增加类型验证逻辑
- 性能优化
- 对CustomField查询结果进行缓存
- 批量处理自定义字段操作
- 前端优化
- 可以添加字段分组显示
- 实现字段排序和验证规则
这个实现方案的核心优势是 简洁稳定 ,通过JSON字段的灵活性和Django表单的动态生成能力,实现了完全可扩展的自定义字段功能,无需修改数据库结构即可添加新字段。
方法2:使用Django包
2-1:django-eav2(推荐)
链接:https://pypi.org/project/django-eav2/
EAV包安装后,在admin有四个菜单:值、属性、枚举值、枚举组
》值:存储实体-属性-值的具体数据记录
功能:查看所有实体对象的属性值数据、管理具体的属性值分配、跟踪每个对象的具体属性值

》属性:定义可用的属性字段模板
功能:创建和管理自定义属性字段
设置属性类型:文本、日期、浮点数、整数、布尔值、Django对象、多项选择、JSON对象、字符分隔值(CSV);
属性名称、短标识符(Slug)、是否必填、实体内容类型(选择可用数据模型、需正确注册eav到对应的数据模型)、选项组、描述、显示顺序
注:未支持图片、视频、文件类型(这二种可能要自定义,只保存对应文件路径)

》枚举值:预定义属性值
预定义选项:为 EAV 属性提供固定的可选值、数据一致性:确保输入值的标准化、下拉选择:在表单中显示为下拉菜单或单选按钮

》枚举组:将枚举值进行分组,“属性”可以选择值为枚举组,从而限制属性的值
分组管理:将相关的枚举值组织在一起
复用性:同一个枚举组可以被多个属性共享
逻辑分类:按业务逻辑对选项进行分类

遇到的问题
问:所有自定义数据模型都显示了所有的EAV属性,没有按“属性“选择的可用模型来显示
# 原始代码 - 没有过滤机制
eav.register(Vehicle)
eav.register(Schedule)
这导致所有EAV属性都会显示在每个模型的admin界面中,无论该属性是否与当前模型相关。
### 技术层面的问题
- 缺少ContentType关联 :EAV属性没有与特定的模型类型建立关联关系
- 默认行为 :django-eav2默认会显示所有可用的EAV属性,不进行任何过滤
- admin界面混乱 :用户在编辑Vehicle时会看到Schedule相关的属性,反之亦然
## 解决方案
### 1. 创建自定义EAV配置类
我在 `models.py` 中添加了两个自定义配置类:
from django.contrib.contenttypes.models import ContentType
from eav.registry import EavConfig
from django.db import models
class VehicleEavConfig(EavConfig):
#继承自 EavConfig,这是 EAV2 包的基类配置
#用于自定义 Vehicle 模型的 EAV 行为
@classmethod
def get_attributes(cls, instance=None):
#get_attributes 是一个类方法,用于获取可用的 EAV 属性
#instance 参数是可选的车辆实例(可以为 None)
from eav.models import Attribute
vehicle_ct = ContentType.objects.get_for_model(Vehicle)
return Attribute.objects.filter(
models.Q(entity_ct=vehicle_ct) | models.Q(entity_ct__isnull=True)
).distinct()
'''
过滤条件解释:
models.Q(entity_ct=vehicle_ct):选择明确指定给 Vehicle 模型的属性
models.Q(entity_ct__isnull=True):选择没有指定特定模型的全局属性
|(或操作符):合并上述两种情况的属性
.distinct():去除重复的属性
models.Q 是 Django 中的一个高级查询工具,用于构建复杂的数据库查询条件。
'''
class ScheduleEavConfig(EavConfig):
@classmethod
def get_attributes(cls, instance=None):
from eav.models import Attribute
schedule_ct = ContentType.objects.get_for_model(Schedule)
return Attribute.objects.filter(
models.Q(entity_ct=schedule_ct) | models.Q(entity_ct__isnull=True)
).distinct()
### 2. 更新EAV注册
将原来的简单注册替换为使用自定义配置的注册:
# 修改后的注册方式
eav.register(Vehicle, VehicleEavConfig)
eav.register(Schedule, ScheduleEavConfig)
## 关键技术点
### 1. ContentType过滤机制
- 使用 entity_ct 字段(ManyToManyField)建立属性与模型的关联
- 通过 ContentType.objects.get_for_model() 获取特定模型的ContentType
- 使用 Q(entity_ct=specific_ct) | Q(entity_ct__isnull=True) 确保兼容性
### 2. 兼容性考虑
- 包含 entity_ct__isnull=True 条件,确保未指定ContentType的通用属性仍然可见
- 使用 .distinct() 避免重复结果
## 修改的文件
### 主要修改:models.py
- 导入语句 :
from django.contrib.contenttypes.models import ContentType
from eav.registry import EavConfig
2. 新增配置类 :
- VehicleEavConfig 类(约15行代码)
- ScheduleEavConfig 类(约15行代码)
- 更新注册调用 :
# 从这样:
eav.register(Vehicle)
eav.register(Schedule)
# 改为这样:
eav.register(Vehicle, VehicleEavConfig)
eav.register(Schedule, ScheduleEavConfig)
## 最终效果
现在admin界面中:
- Vehicle编辑页面 :只显示与车辆相关的属性(如 color )
- Schedule编辑页面 :只显示与排班相关的属性(如 age 、 commission_rate )
- 通用属性 :未指定ContentType的属性在所有模型中都可见
这样就彻底解决了"所有EAV属性都显示在每个模型中"的问题,实现了按实体内容类型的精确过滤。
问:现在自定义模型显示了eav关联的属性,但系统模型显示不了关联的eav属性,比如eav属性中age我关联了”用户“表
系统模型(如User)的admin界面中看不到这些EAV属性。这是因为Django的内置模型(如User)默认没有启用EAV支持。
启用步骤:
- 为Django User模型注册EAV支持,创建UserEavConfig类
- 更新admin.py,为User模型添加EAV支持的admin配置
- 测试User模型在admin界面中是否正确显示EAV属性
注意事项:
- EAV系统会强制覆盖User模型的管理器为 EntityManager
- 直接继承或替换管理器都会被EAV系统覆盖
- 需要找到一种方法让 EntityManager 具备 UserManager 的功能
### 2. 解决方案
我直接为EAV的 EntityManager 类添加了 UserManager 的关键方法:
# 为EAV的EntityManager添加UserManager的方法
from eav.managers import EntityManager
from django.contrib.auth.models import UserManager
# 添加UserManager的所有关键方法到EntityManager
EntityManager.normalize_email = UserManager.normalize_email
EntityManager.create_user = UserManager.create_user
EntityManager.create_superuser = UserManager.create_superuser
EntityManager._create_user = UserManager._create_user
EntityManager._create_user_object = UserManager._create_user_object
EntityManager.with_perm = UserManager.with_perm
2-2:django-dynamic-model
允许在运行时动态的创建和更新数据库模式,包不活跃,过去12个月未维护,不建议使用。
2-5:django-custom-field
新建数据模型时通过继承此包,获取自定义字段的能力,核心原理也是使用EAV模式。
缺点:个人维护,功能较少,兼容性差,不建议使用。
django-eav2:
- ✅ 活跃维护 :由 Jazzband 组织维护,这是一个专门维护 Django 包的社区组织
- ✅ 持续更新 :2024年仍有活跃的提交和发布
- ✅ 社区支持 :GitHub 上有 357+ stars,社区相对活跃
- ✅ 现代 Django 支持 :支持最新的 Django 版本
django-custom-field:
- ❌ 维护状态不明 :个人维护项目,更新频率较低
- ❌ 兼容性问题 :如我们之前遇到的,与新版 Django 存在兼容性问题
- ❌ 社区较小 :相对较少的社区支持和贡献
