gpt4 book ai didi

django - 将 Django 字段描述从现有模型复制到新模型

转载 作者:行者123 更新时间:2023-12-04 17:53:22 24 4
gpt4 key购买 nike

我正在尝试根据现有模型中的字段动态生成新模型。两者都在 /apps/main/models.py 中定义.现有模型如下所示:

from django.db import models

class People(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
height = models.IntegerField()

我有一个包含要复制的字段名称的列表:
target_fields = ["name", "age"]

我想生成一个新模型,该模型具有 target_fields 中命名的所有字段,但在这种情况下,它们应该被索引( db_index = True )。

我最初希望我能够迭代 People 的类属性。并使用 copy.copy复制在其上定义的字段描述。像这样:
from copy import copy

d = {}
for field_name in target_fields:
old_field = getattr(People, field_name) # alas, AttributeError
new_field = copy(old_field)
new_field.db_index = True
d[field_name] = new_field

IndexedPeople = type("IndexedPeople", (models.Model,), d)

我不确定是否 copy.copy() ing Fields 可以工作,但我没有深入了解:类定义中列出的字段实际上并未作为类对象的属性包含在内。我假设它们被用于一些元类恶作剧。

在调试器中摸索之后,我发现了一些列在 People._meta.local_fields 中的 Field 对象类型。 .然而,这些不仅仅是简单的描述,可以是 copy.copy() ed 并用于描述另一个模型。例如,它们包括 .model属性引用 People .

如何基于现有模型的字段为新模型创建字段描述?

最佳答案

从调试器和源代码中寻找:所有 Django 模型都使用 ModelBase /db/models/base.py 中定义的元类.对于模型类定义中的每个字段,ModelBase.add_to_class方法将调用该字段的 .contribute_to_class方法。
Field.contribute_to_class /db/models/fields/__init__.py 中定义它负责将字段定义与特定模型相关联。通过添加 .model 修改该字段属性并通过调用 .set_attributes_from_name具有模型类定义中使用的名称的方法。这反过来又增加了 .attname.column属性和集 .name.verbose_name如有必要。

当我检查 __dict__新定义的属性 CharField并将其与 CharField 的比较已经与模型相关联,我还看到这些是唯一的区别:

  • .creation_counter属性对于每个实例都是唯一的。
  • .attrname , .column.model新实例上不存在属性。
  • .name.verbose_name属性是 None在新实例上。

  • 似乎无法区分 .name/ .verbose_name手动指定给构造函数的属性和自动生成的属性。您需要选择始终重置它们,忽略任何手动指定的值,或者从不清除它们,这将导致它们始终忽略在新模型中给定的任何新名称。我想使用与原始字段相同的名称,所以我不打算碰它们。

    知道存在哪些差异,我正在使用 copy.copy()克隆现有实例,然后应用这些更改使其表现得像一个新实例。
    import copy
    from django.db import models

    def copy_field(f):
    fp = copy.copy(f)

    fp.creation_counter = models.Field.creation_counter
    models.Field.creation_counter += 1

    if hasattr(f, "model"):
    del fp.attname
    del fp.column
    del fp.model

    # you may set .name and .verbose_name to None here

    return fp

    鉴于此功能,我使用以下内容创建新模型:
    target_field_name = "name"

    target_field = People._meta.get_field_by_name(target_field_name)[0]
    model_fields = {}

    model_fields["value"] = copy_field(target_field)
    model_fields["value"].db_index = True
    model_fields["__module__"] = People.__module__

    NewModel = type("People_index_" + field_name, (models.Model,), model_fields)

    有用!

    关于django - 将 Django 字段描述从现有模型复制到新模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12222003/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com