create()をオーバーライドする代わりに、Django models.Managerでcreate_foo()を定義するのはなぜですか?


10

Djangoのドキュメントを読んで、マネージャの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")

常に完全にバイパスできる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客観的に優れているだけのオーバーライドですか?

回答:


10

はい、もちろん、それを行うことができます。しかし、ドキュメントから引用している例をよく見ると、createをオーバーライドする必要があるかどうかではなく、

ただし、変更する場合は変更を加えないように注意してください。変更すると、モデルインスタンスが保存されなくなる可能性があります。

呼び出し署名を保持します。あなたが利用できるインターフェースは、djangoが内部的に使用することもあるからです。それらを変更した場合、Djangoにとってはうまくいきません。

この例ではcreate、モデルコンストラクターを提案しているのではありません。

第二に、標準インターフェースでさえcreateキーワード引数のみをとります

def create(self, **kwargs):

ただし、位置引数を取るように変更すると、def create(self, title):Django内または標準的な方法で使用されている場所で中断します。あなたが必要がありますので、拡張機能は、既存のない変更と、おそらく壊れて。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.