如何从Python中的给定文本创建一组类及其变量和方法

2024-04-12

我想从给定的文本配置创建一组类、其变量和方法,特别是使用 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 确保它使用该配置在我的数据库中创建表


我可以从两个角度来看这个问题

  1. 动态创建Python类的正常方式
  2. 专门创建动态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这会工作得很好,但有一些事情需要注意

  1. 字段属性应该小心处理,因为您将从文本文件中读取它
  2. 应使用 locals() 添加模型以从应用程序导入模型
  3. 方法 create_model 应取自参考链接,因为它支持更多功能,例如添加管理页面等
  4. 数据迁移也适用于这种模型

我的建议

上述方法可以毫无问题地工作,并且所有这些方法都受支持,但不要忘记的一件事是,动态导入的类和实际导入存在性能差异。另外,这是一个有点复杂的结构,代码中的任何更改都应该非常小心,以免破坏它。

所以我的建议是读取带有配置的文本文件并生成 models.py使用一些神奇的脚本(也可以在 python 中创建)从配置文件中创建文件。 因此,每次文本配置文件发生更改时,您都必须生成 models.py 脚本。这样您还可以确保模型定义

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从Python中的给定文本创建一组类及其变量和方法 的相关文章

随机推荐