¿Por qué definir create_foo () en un Django models.Manager en lugar de anular create ()?

10

Al leer los documentos de Django , se aconseja crear un método de creación personalizado para un modelo denominado Foodefiniéndolo como create_fooen el administrador:

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

Mi pregunta es por qué se prefiere el anterior a simplemente anular el createmétodo de la clase 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 parece que solo anular createevitará que alguien lo use accidentalmente para hacer una instancia de modelo mal formada, ya create_fooque siempre se puede omitir por completo:

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

¿Hay alguna ventaja en hacerlo como sugieren los documentos, o en realidad se anula createsolo objetivamente mejor?

ruohola
fuente

Respuestas:

10

Sí, obviamente, puedes hacer eso. Pero si mira más de cerca el ejemplo que está citando de la documentación, no se trata de si debe anular crear o no, se trata de

Sin embargo, si lo hace, tenga cuidado de no cambiar la firma de llamada, ya que cualquier cambio puede evitar que se guarde la instancia del modelo.

preservando la firma de llamada . Porque las interfaces disponibles para usted también pueden ser utilizadas internamente por django. Si los modifica, es posible que las cosas no se rompan para usted sino para Django.

En este ejemplo, no sugieren esto para createsino el constructor de modelos.

En segundo lugar , incluso la interfaz estándar para createsolo toma argumentos de palabras clave

def create(self, **kwargs):

Pero si lo modifica para tomar argumentos posicionales, def create(self, title):se romperá donde sea que se use dentro de Django o de manera estándar. Por lo tanto, debe ampliar la funcionalidad existente, no modificarla y, muy probablemente, romperla .

Nafees Anwar
fuente