为什么要在Django模型中定义create_foo()。Manager而不是覆盖create()?

问题描述 投票:2回答:1

[读取Django docs,建议通过在管理器中将其定义为Foo,为名为create_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")

我的问题是,为什么上一个为什么要优先于简单地重写基类的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

python django django-models django-managers
1个回答
1
投票
是的,显然,您可以这样做。但是,如果您更仔细地看文档中引用的示例,则与您是否应覆盖create无关,而与[]有关。

但是,如果这样做,请注意不要更改呼叫签名因为任何更改都可能导致模型实例无法保存。

保留主叫签名

。因为django内部还可以使用为您提供的接口。如果您修改它们,那么事情可能不会对您造成破坏,而是让Django正常工作。在此示例中,他们不建议create使用此方法,而建议使用模型构造函数。

第二

,甚至create的标准接口也只接受关键字参数
def create(self, **kwargs):
但是如果您修改它以接受位置参数,则def create(self, title):它将在Django内部或标准方式中使用的任何位置中断。因此,您应该

extend

现有功能而不是modify,并且很可能break它。
© www.soinside.com 2019 - 2024. All rights reserved.