Perché definire create_foo () in un modello Django.Manager invece di sovrascrivere create ()?


10

Leggendo i documenti di Django , si consiglia di creare un metodo di creazione personalizzato per un modello denominato Foodefinendolo come create_foonel gestore:

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

La mia domanda è: perché il precedente è preferito semplicemente sovrascrivere il createmetodo della classe base :

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 sembra che solo l'override createimpedirà a chiunque di utilizzarlo accidentalmente per creare un'istanza del modello non valida, poiché create_foopuò sempre essere bypassato completamente:

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

C'è qualche vantaggio nel farlo come suggeriscono i documenti o in realtà scavalcare createsolo oggettivamente meglio?

Risposte:


10

Sì, ovviamente, puoi farlo. Ma se guardi più vicino all'esempio che stai citando dalla documentazione, non si tratta di sostituire o meno la creazione, ma di

In tal caso, tuttavia, fare attenzione a non modificare la firma della chiamata poiché qualsiasi modifica potrebbe impedire il salvataggio dell'istanza del modello.

preservare la firma chiamante . Perché le interfacce disponibili per te possono anche essere utilizzate internamente da Django. Se le modifichi, le cose potrebbero non andare bene per te ma per Django.

In questo esempio, non stanno suggerendo questo per createma il costruttore del modello.

In secondo luogo , anche l'interfaccia standard richiede createsolo argomenti di parole chiave

def create(self, **kwargs):

Ma se lo modifichi per accettare argomenti posizionali, def create(self, title):si romperà ovunque sia usato all'interno di Django o in modo standard. Quindi dovresti estendere le funzionalità esistenti non modificarle e molto probabilmente romperle .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.