Навіщо визначати create_foo () в моделях Django. Менеджер замість переопределення create ()?


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

Так, очевидно, ви можете це зробити. Але якщо ви придивитесь ближче до прикладу, який ви цитуєте з документації, мова не йде про те, чи слід переосмислювати створення, чи ні, це про

Якщо ви це зробите, подбайте про те, щоб не змінювати підпис виклику, оскільки будь-яка зміна може не допустити збереження екземпляра моделі.

збереження підпису дзвінка . Оскільки доступні для вас інтерфейси також можуть використовувати django внутрішньо. Якщо ви модифікуєте їх, все може не зламатися для вас, але для Джанго.

У цьому прикладі вони пропонують це не для createконструктора моделей.

По-друге , навіть стандартний інтерфейс для createприймає лише аргументи ключових слів

def create(self, **kwargs):

Але якщо ви модифікуєте його на позиційні аргументи, def create(self, title):він порушиться, де б він не використовувався всередині Django або стандартним чином. Тож вам слід розширити існуючу функціональність, а не змінювати її і, швидше за все, порушити .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.