Warum sollte create_foo () in einem Django-Modell definiert werden? Manager, anstatt create () zu überschreiben?

10

Beim Lesen der Django-Dokumente wird empfohlen, eine benutzerdefinierte Erstellungsmethode für ein Modell zu erstellen , Fooindem Sie es wie create_fooim Manager definieren:

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")

Meine Frage ist, warum die vorherige der einfachen Überschreibung der createMethode der Basisklasse vorgezogen wird:

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 scheint es, dass nur das Überschreiben createverhindert, dass jemand es versehentlich verwendet, um eine fehlerhafte Modellinstanz zu erstellen, da create_fooimmer vollständig umgangen werden kann:

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")

Gibt es einen Vorteil, wenn Sie dies tun, wie es die Dokumente vorschlagen, oder ist das Überschreiben createnur objektiv besser?

Ruohola
quelle

Antworten:

10

Ja, das können Sie natürlich. Wenn Sie sich jedoch das Beispiel genauer ansehen, das Sie aus der Dokumentation zitieren, geht es nicht darum, ob Sie create überschreiben sollen oder nicht, es geht darum

Wenn Sie dies tun, achten Sie jedoch darauf, die aufrufende Signatur nicht zu ändern, da durch Änderungen möglicherweise verhindert wird, dass die Modellinstanz gespeichert wird.

Beibehaltung der aufrufenden Signatur . Weil für Sie verfügbare Schnittstellen auch intern von django verwendet werden können. Wenn Sie sie ändern, können die Dinge nicht für Sie, sondern für Django brechen.

In diesem Beispiel schlagen sie dies nicht für einen createModellkonstruktor vor.

Zweitens verwendet sogar die Standardschnittstelle für createnur Schlüsselwortargumente

def create(self, **kwargs):

Wenn Sie es jedoch so ändern, dass es Positionsargumente enthält, wird def create(self, title):es überall dort unterbrochen, wo es in Django oder auf standardmäßige Weise verwendet wird. So sollten Sie erweitern vorhandene Funktionalität nicht ändern und wahrscheinlich brechen sie.

Nafees Anwar
quelle