python - 如何从python中的给定文本创建一组类及其变量和方法
问题描述
我想从给定的文本配置中创建一组类,它的变量和方法,尤其是 django 模型,例如,我有一个模型列表要在 models.py 中创建
classes=["users", "posts", "commnets"]
vars= [{"a","b"},{"bb","vv"},{"aa"}]
#methods=[{....},{....},{....}] not now
在models.py中,我想做这样的事情来创建那些类
for i,j in zip(classes,vars):
create_classes_from_string(i,j)
我如何编程#create_classes_from_string 以确保它使用该配置在我的数据库中创建表
解决方案
我可以从两个角度看待这个问题
- 动态创建python类的正常方法
- 专门创建动态 django 模型
但在这两种情况下,attrs 都应该定义为带有变量名及其值的 dict。因为在这里定义一个没有值的变量是没有意义的。
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()
输出
>>> 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
一个例子可以看如下,你可以直接将下面的脚本添加到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 应取自参考链接,因为它支持更多功能,例如添加管理页面等
- 数据迁移也适用于这种模型
我的建议
上述方法可以毫无问题地工作,并且所有这些方法都受支持,但不要忘记一件事,动态导入的类和真正的导入存在性能差异。此外,这是一个有点复杂的结构,代码中的任何更改都应该非常小心地进行,以免破坏它。
所以我的建议是读取带有配置的文本文件,并使用一些魔法脚本(也可以在 python 中创建)从配置文件中生成 models.py 文件。因此,每次 text-config 文件发生更改时,您都必须生成 models.py 脚本。这样您还可以确保模型定义
推荐阅读
- python - 将两列除以两列
- c# - Xamarin iOS 项目中的 BindableRadioGroup
- google-apps-script - AppScript 中的异步
- node.js - 节点 sqlite3 lastID 没有返回
- swift - SwiftUI 设置发布的变量会破坏程序
- python - 使用 minimumModbus 存储 modbus 消息
- delphi - 使用带有帧的 ActiveControl 属性将焦点转发到子组件
- python - Python:文本的正则表达式
- python - 如何按每个元素的不同顺序对元组列表进行排序?
- svelte - SvelteKit SSR - 如何在获取数据之前阻止服务器端渲染?