Mengapa mendefinisikan create_foo () di model Django. Manajer bukannya mengganti create ()?

10

Membaca dokumen Django , disarankan untuk membuat metode pembuatan kustom untuk model yang dinamai Foodengan mendefinisikannya sebagai create_foodi manajer:

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

Pertanyaan saya adalah mengapa mengapa yang sebelumnya lebih disukai daripada hanya meng-override metode kelas dasar 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")

Imo tampaknya hanya meng create- override akan mencegah siapa pun menggunakannya secara tidak sengaja untuk membuat contoh model yang cacat, karena create_fooselalu dapat dilewati sepenuhnya:

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

Apakah ada keuntungan dalam melakukannya seperti yang disarankan dokumen, atau sebenarnya mengesampingkan secara createobjektif lebih baik?

ruohola
sumber

Jawaban:

10

Ya, jelas, Anda bisa melakukannya. Tetapi jika Anda melihat lebih dekat dengan contoh yang Anda kutip dari dokumentasi, ini bukan tentang apakah Anda harus menimpa membuat atau tidak, ini tentang

Namun, jika Anda melakukannya, berhati-hatilah untuk tidak mengubah tanda tangan panggilan karena perubahan apa pun dapat mencegah model instance dari disimpan.

menjaga tanda tangan panggilan . Karena antarmuka yang tersedia untuk Anda juga dapat digunakan oleh Django secara internal. Jika Anda memodifikasinya, hal-hal yang mungkin tidak merusak untuk Anda tetapi untuk Django.

Dalam contoh ini, mereka tidak menyarankan ini untuk createtetapi konstruktor model.

Kedua , bahkan antarmuka standar untuk createhanya mengambil argumen kata kunci

def create(self, **kwargs):

Tetapi jika Anda memodifikasinya untuk mengambil argumen posisi, def create(self, title):itu akan pecah di mana pun itu digunakan di dalam Django atau dengan cara standar. Jadi, Anda harus memperluas fungsi yang ada tidak memodifikasi dan kemungkinan besar merusaknya .

Nafees Anwar
sumber