Django Model () vs Model.objects.create ()

267

Apa perbedaan antara menjalankan dua perintah:

foo = FooModel()

dan

bar = BarModel.objects.create()

Apakah yang kedua segera membuat BarModeldalam database, sedangkan untuk FooModel, save()metode harus dipanggil secara eksplisit untuk menambahkannya ke database?

0leg
sumber
47
Ya, itulah bedanya.
Daniel Roseman

Jawaban:

247

https://docs.djangoproject.com/en/stable/topics/db/queries/#creating-objects

Untuk membuat dan menyimpan objek dalam satu langkah, gunakan create()metode ini.

madzohan
sumber
3
Dokumen Django agak bertentangan tentang hal ini menurut saya. Saya memiliki pertanyaan yang sama dan membaca "Perhatikan bahwa instantiating model sama sekali tidak menyentuh database Anda; untuk itu, Anda perlu menyimpan ()." docs.djangoproject.com/en/1.10/ref/models/inances/…
Nils
6
Saya tidak melihatnya sebagai kontradiktif. Umumnya dalam python, Anda membuat instance objek dengan menempatkan tanda kurung setelah nama Objects bukan dengan metode create
danidee
3
@danidee Saya setuju itu tidak bertentangan, tetapi tentu saja menyesatkan. Terutama karena di tautan Nils, example1 adalah "instantiating" tetapi example2 adalah "instantiating + saving". Juga, mengapa saya harus merujuk ke dokumen "kueri" ketika saya ingin tahu cara menyimpan model? Sebenarnya ada banyak kesakitan di Django Doc.
Nakamura
3
@Nakamura karena INSERT adalah kueri?
Juanjo Conti
16

Kedua sintaks tidak sama dan dapat menyebabkan kesalahan yang tidak terduga. Berikut adalah contoh sederhana yang menunjukkan perbedaan. Jika Anda memiliki model:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

Dan Anda membuat objek pertama:

foo = Test.objects.create(pk=1)

Kemudian Anda mencoba membuat objek dengan kunci utama yang sama:

foo_duplicate = Test.objects.create(pk=1)
# returns the error:
# django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'")

foo_duplicate = Test(pk=1).save()
# returns the error:
# django.db.utils.IntegrityError: (1048, "Column 'added' cannot be null")
Thomas Leonard
sumber
jadi .create()membuat objek bahkan jika bidang yang diperlukan ( null=False) hilang? Saya menambahkan tes pada proyek saya dan createmendapatkan hasil yang tidak terduga
Vaibhav Vishal
Tidak, seharusnya tidak ... Meskipun beberapa tipe bidang bertingkah agak aneh di Django. Misalnya, CharFieldbahkan jika disetel ke null=Falsetidak akan menimbulkan kesalahan jika tidak disediakan: ini karena Django menetapkan string secara default ke string kosong ""sehingga tidak secara teknisnull
Thomas Leonard
ya, saya mengalami masalah hanya dengan bidang char dan bidang lapangan (yang pada dasarnya adalah bidang char juga). Menggunakan obj = MyModel(), lalu obj.full_clean()untuk sekarang.
Vaibhav Vishal
10

PEMBARUAN 15.3.2017:

Saya telah membuka masalah Django tentang hal ini dan tampaknya akan diterima di sini: https://code.djangoproject.com/ticket/27825

Pengalaman saya adalah bahwa ketika menggunakan kelas Constructor( ORM) dengan referensi dengan Django 1.10.5mungkin ada beberapa ketidakkonsistenan dalam data (yaitu atribut dari objek yang dibuat mungkin mendapatkan tipe data input daripada tipe cast dari properti objek ORM) contoh :

models

class Payment(models.Model):
     amount_cash = models.DecimalField()

some_test.py - object.create

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor.objects.create(**actual_data)
            print(type(_obj.amount_cash)) # Decimal
            assert created
           objs.append(_obj)
        return objs

some_test.py - Constructor()

Class SomeTestCase:
    def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
        objs = []
        if not base_data:
            base_data = {'amount_case': 123.00}
        for modifier in modifiers:
            actual_data = deepcopy(base_data)
            actual_data.update(modifier)
            # Hacky fix,
            _obj = _constructor(**actual_data)
            print(type(_obj.amount_cash)) # Float
            assert created
           objs.append(_obj)
        return objs
Oleg Belousov
sumber
Josh Smeaton memberikan jawaban yang sangat baik mengenai tanggung jawab pengembang sendiri untuk melemparkan tipe. Harap perbarui jawaban Anda.
Artur Barseghyan