django-models - Django 中的 DRY 唯一对象

标签 django-models refactoring dry

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

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

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 反而?

最佳答案

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

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

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

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

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

    以下是有关如何实现目标的秘诀:
  • 子类 ModelBase使用你自己的元类。
  • 覆盖方法 __new__(cls, name, bases, dict)
  • 检查 dict收集Meta成员 ( dict["Meta"] ) 以及所有现场成员
  • 套装meta.unique_together根据您收集的字段名称。
  • 调用 super 实现 ( ModelBase.__new__ )
  • 使用魔法成员 __metaclass__ = MyMetaclass 为所有独特模型使用自定义元类(或派生一个抽象基类扩展 Model 并覆盖元类)
  • 关于django-models - Django 中的 DRY 唯一对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1389443/

    相关文章:

    python - Django objects.filter() values_list() vs python list comprehension for __in query

    ruby-on-rails - 根据管理员是否在场重构 ruby​​ 代码

    ruby-on-rails - Rspec 的 DRY 问题我该如何解决

    没有重载或泛型的 C# 多参数类型

    python - model.py 更改后 Django 站点预览未更新

    python - django中的图书馆管理系统

    python - Django ORM : Joining QuerySets

    refactoring - python : Detect code which gets never executed in production

    c++ - 根据调用者/上下文专门化函数的行为

    ruby-on-rails - 救援中的 DRY 代码 => Rails 中各种模型文件中的 e