Cara yang benar untuk menggunakan get_or_create?

203

Saya mencoba menggunakan get_or_create untuk beberapa bidang dalam formulir saya, tetapi saya mendapatkan 500 kesalahan ketika saya mencoba melakukannya.

Salah satu garis terlihat seperti ini:

customer.source = Source.objects.get_or_create(name="Website")

Kesalahan yang saya dapatkan untuk kode di atas adalah:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.
Stephen
sumber

Jawaban:

353

Dari dokumentasi get_or_create :

# get_or_create() a person with similar first names.

p, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

# get_or_create() didn't have to create an object.
>>> created
False

Penjelasan: Bidang yang akan dievaluasi kesamaan, harus disebutkan di luar defaults. Sisa bidang harus disertakan dalam defaults. Jika terjadi CREATE, semua bidang dipertimbangkan.

Sepertinya Anda perlu kembali ke tuple, alih-alih variabel tunggal, lakukan seperti ini:

customer.source,created = Source.objects.get_or_create(name="Website")
Bryan Rehbein
sumber
3
FYI yang dibuat adalah boolean. Benar jika dibuat, Salah jika diambil
Josh
3
Tambahan tambahan save()?
zypro
@zypro Seperti create(), buat objek dan simpan semuanya dalam satu langkah dan tidak perlusave()
Amin Mir
32

get_or_create mengembalikan tuple.

customer.source, created = Source.objects.get_or_create(name="Website")
Tobu
sumber
16
Atau, jika Anda tidak peduli dengan bendera boolean:customer.source = Source.objects.get_or_create(name="Website")[0]
mipadi
7
@ mipadi saya lebih suka customer.source, _ = Source.objects.get_or_create(name="Website"), karena membuat fakta bahwa tuple dikembalikan lebih jelas, membantu menghindari bug di masa depan.
Solomon Ucko
15

get_or_create() mengembalikan tuple:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created memiliki nilai boolean, dibuat atau tidak.

  • customer.source memiliki objek get_or_create()metode.

Tushar.PUCSD
sumber
12

Mengikuti jawaban @Tobu dan komentar @mipadi, dengan cara yang lebih pythonic, jika tidak tertarik pada flag yang dibuat, saya akan menggunakan:

customer.source, _ = Source.objects.get_or_create(name="Website")
jbondia
sumber
4

Masalah yang Anda temui adalah fitur terdokumentasi dari get_or_create.

Saat menggunakan argumen kata kunci selain "default", nilai balik dari get_or_createadalah contoh. Itu sebabnya ini menunjukkan kepada Anda parens dalam nilai pengembalian.

Anda bisa menggunakan customer.source = Source.objects.get_or_create(name="Website")[0]untuk mendapatkan nilai yang benar.

Berikut ini tautan untuk dokumentasi: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

wlashell
sumber