为什么在 Django models.Manager 中定义 create_foo() 而不是覆盖 create()?

Why define create_foo() in a Django models.Manager instead of overriding create()?

阅读 Django docs,它建议通过在管理器中将其定义为 create_foo 来为名为 Foo 的模型创建自定义创建方法:

class BookManager(models.Manager):
    def create_book(self, title):
        book = self.create(title=title)
        # do something with the book
        return book

class Book(models.Model):
    title = models.CharField(max_length=100)

    objects = BookManager()

book = Book.objects.create_book("Pride and Prejudice")

我的问题是,为什么前一个更喜欢简单地覆盖基础 class 的 create 方法:

class BookManager(models.Manager):
    def create(self, title):
        book = self.model(title=title)
        # do something with the book
        book.save()
        return book

class Book(models.Model):
    title = models.CharField(max_length=100)

    objects = BookManager()

book = Book.objects.create("Pride and Prejudice")

Imo 似乎只有重写 create 才能防止任何人意外使用它来制作格式错误的模型实例,因为 create_foo 总是可以完全绕过:

class BookManager(models.Manager):
    def create_book(self, title):
        book = self.create(title=title, should_not_be_set_manually="critical text")
        return book

class Book(models.Model):
    title = models.CharField(max_length=100)
    should_not_be_set_manually = models.CharField(max_length=100)

    objects = BookManager()

# Can make an illformed Book!!
book = Book.objects.create(title="Some title", should_not_be_set_manually="bad value")

像文档建议的那样做是否有任何优势,或者实际上压倒 create 只是客观上更好?

是的,显然,你可以做到。但是如果你仔细观察你从文档中引用的例子,这与你是否应该覆盖创建无关,而是关于

If you do so, however, take care not to change the calling signature as any change may prevent the model instance from being saved.

保留调用签名。因为你可用的接口也可能被 django 内部使用。如果您修改它们,事情可能不会对您不利,但对 Django 不利。

在这个例子中,他们不是为 create 而是为模型构造函数提出建议。

其次,甚至 create 的标准接口也只接受关键字参数

def create(self, **kwargs):

但是如果你修改它以接受位置参数,def create(self, title): 它会在 Django 内部或以标准方式使用它的任何地方中断。因此,您应该 扩展 现有功能而不是 修改 并且很可能 破坏 它。