我可以从两个角度来看这个问题
- 动态创建Python类的正常方式
- 专门创建动态django模型
但在这两种情况下,属性都应该定义为带有变量名称及其值的字典。因为在这里定义一个没有值的变量是没有意义的。
1.动态创建python类的正常方式
这里我们可以简单地使用type()生成Python类的方法。稍后可以通过将其添加到 locals() 内置函数来创建具有自己名称的对象。
下面提到一个例子
classes = ["Class1", "Class2"]
class_fileds = [
{
'cl1_var1': "test",
'cl1_var2': 123,
},
{
'cl2_var1': [1, 2, 3],
}
]
classes_details = list(zip(classes, class_fileds)) # Python3 format
for class_details in classes_details:
class_name = class_details[0]
class_attrs = class_details[1]
class_def = type(
class_name,
(object, ), # Base classes tuple
class_attrs
)
locals().update({class_name: class_def}) # To associate the class with the script running
instance1 = Class1()
instance2 = Class2()
Outputs
>>> instance1 = Class1()
>>> instance2 = Class2()
>>>
>>> instance1.cl1_var1
'test'
>>> instance1.cl1_var2
123
>>> instance2.cl2_var1
[1, 2, 3]
这里列表中的类名,classes = ["Class1", "Class2"],可以像给定的那样使用,即 Class1()、Class2() 等。这是通过将变量 Class1 和 Class2 添加到运行中来实现的脚本通过使用 local() 动态地内置功能
2.专门创建动态django模型
尽管基本逻辑保持不变,但仍需要进行一些更改。
首先我们需要了解Django中的动态模型创建。 Django 为此提供了清晰的文档。
请参考,https://code.djangoproject.com/wiki/DynamicModels https://code.djangoproject.com/wiki/DynamicModels
示例如下,可以直接将以下脚本添加到 models.py 文件中
from django.db import models
from django.db.models import CharField, IntegerField
# This is taken from https://code.djangoproject.com/wiki/DynamicModels#Ageneral-purposeapproach
def create_model(name, fields=None, app_label='', module='', options=None, admin_opts=None):
class Meta:
pass
if app_label:
setattr(Meta, 'app_label', app_label)
if options is not None:
for key, value in options.iteritems():
setattr(Meta, key, value)
attrs = {'__module__': module, 'Meta': Meta} # Set up a dictionary to simulate declarations within a class
if fields: # Add in any fields that were provided
attrs.update(fields)
model = type(name, (models.Model,), attrs) # Create the class, which automatically triggers ModelBase processing
return model
classes = ["Class1", "Class2"]
class_fileds = [
{
'cl1_var1': CharField(max_length=255),
'cl1_var2': IntegerField(),
},
{
'cl2_var2': IntegerField(),
}
]
models_details = list(zip(classes, class_fileds))
for model_detail in models_details:
model_name = model_detail[0]
model_attrs = model_detail[1]
model_def = create_model(
model_name,
fields=model_attrs,
app_label=__package__,
module= __name__,
)
locals()[model_name] = model_def
django shell 的输出
>>> from my_app.models import Class1
>>> Class1(cl1_var1="Able to create dynamic class", cl1_var2=12345).save()
>>> Class1.objects.all().values()
<QuerySet [{'cl1_var1': 'Able to create dynamic class', 'id': 3, 'cl1_var2': 12345}]>
这个模型被添加到django应用程序中,my_app这会工作得很好,但有一些事情需要注意
- 字段属性应该小心处理,因为您将从文本文件中读取它
- 应使用 locals() 添加模型以从应用程序导入模型
- 方法 create_model 应取自参考链接,因为它支持更多功能,例如添加管理页面等
- 数据迁移也适用于这种模型
我的建议
上述方法可以毫无问题地工作,并且所有这些方法都受支持,但不要忘记的一件事是,动态导入的类和实际导入存在性能差异。另外,这是一个有点复杂的结构,代码中的任何更改都应该非常小心,以免破坏它。
所以我的建议是读取带有配置的文本文件并生成 models.py使用一些神奇的脚本(也可以在 python 中创建)从配置文件中创建文件。
因此,每次文本配置文件发生更改时,您都必须生成 models.py 脚本。这样您还可以确保模型定义