5

我想确保一个对象是唯一的,如果不是,当用户尝试保存它(例如通过管理员)时抛出错误?唯一,我的意思是对象的某些属性可能与其他对象的属性值相同,但它们不能都与另一个对象的值相同。

如果我没记错的话,我可以这样做:

class Animal(models.Model):
    common_name = models.CharField(max_length=150)
    latin_name = models.CharField(max_length=150)
    class Meta:
        unique_together = ("common_name", "latin_name")

但是每次我重构模型时(例如添加一个新字段,或更改现有字段的名称),我还必须编辑分配给unique_together的括号中的字段列表。使用简单的模型没关系,但如果使用大量模型,重构过程中就会变得非常麻烦。

如何避免在unique_together括号中重复输入字段名称列表?有没有办法将模型的字段列表传递给一个变量并将该变量分配给unique_together呢?

4

1 回答 1

4

重构模型是一件相当昂贵的事情:

  • 您需要使用模型更改所有代码,因为字段名称对应于对象属性
  • 您将不得不手动更改数据库,因为 Django 无法为您执行此操作(至少我上次使用 Django 时使用的版本不能)

因此,我认为更新模型元类中的唯一字段名称列表是您最不应该担心的问题。

编辑:如果你真的想这样字段必须是“唯一的”,那么 freenode 的人是对的,你必须编写一个自定义元类。这非常复杂且容易出错,而且它可能会使您的代码与 Django 的未来版本不兼容。

Django 的 ORM “魔法”由通用基类的元类ModelBase( ) 控制。此类负责获取包含所有字段和元信息的类定义,并构建您稍后将在代码中使用的类。django.db.models.base.ModelBaseModel

以下是有关如何实现目标的秘诀:

  1. ModelBase使用您自己的元类的子类。
  2. 覆盖方法__new__(cls, name, bases, dict)
  3. 检查dict收集Meta成员(dict["Meta"] ) 以及所有现场成员
  4. meta.unique_together根据您收集的字段名称进行设置。
  5. 调用超级实现 ( ModelBase.__new__)
  6. 使用魔术成员为所有独特模型使用自定义元类__metaclass__ = MyMetaclass(或派生抽象基类扩展Model和覆盖元类)
于 2009-09-07T14:39:37.417 回答