Saat Anda memiliki bidang model dengan opsi pilihan, Anda cenderung memiliki beberapa nilai ajaib yang terkait dengan nama yang dapat dibaca manusia. Apakah ada di Django cara mudah untuk menyetel bidang ini dengan nama yang dapat dibaca manusia alih-alih nilainya?
Pertimbangkan model ini:
class Thing(models.Model):
PRIORITIES = (
(0, 'Low'),
(1, 'Normal'),
(2, 'High'),
)
priority = models.IntegerField(default=0, choices=PRIORITIES)
Di beberapa titik kami memiliki instance Thing dan kami ingin menetapkan prioritasnya. Jelas Anda bisa melakukannya,
thing.priority = 1
Tapi itu memaksa Anda untuk menghafal pemetaan Nama-Nilai PRIORITAS. Ini tidak berhasil:
thing.priority = 'Normal' # Throws ValueError on .save()
Saat ini saya memiliki solusi konyol ini:
thing.priority = dict((key,value) for (value,key) in Thing.PRIORITIES)['Normal']
tapi itu kikuk. Mengingat betapa umum skenario ini, saya bertanya-tanya apakah ada yang punya solusi yang lebih baik. Apakah ada metode bidang untuk menyetel bidang dengan nama pilihan yang benar-benar saya abaikan?
sumber
Saya mungkin akan menyiapkan dikt pencarian balik sekali dan untuk selamanya, tetapi jika tidak, saya akan menggunakan:
yang tampaknya lebih sederhana daripada membuat dict dengan cepat hanya untuk membuangnya lagi ;-).
sumber
Berikut adalah jenis bidang yang saya tulis beberapa menit yang lalu yang menurut saya sesuai dengan keinginan Anda. Konstruktornya memerlukan argumen 'pilihan', yang bisa berupa tuple 2-tupel dalam format yang sama dengan pilihan opsi untuk IntegerField, atau sebagai gantinya daftar nama sederhana (yaitu ChoiceField (('Low', 'Normal', 'Tinggi'), default = 'Rendah')). Kelas menangani pemetaan dari string ke int untuk Anda, Anda tidak pernah melihat int.
sumber
Saya menghargai cara mendefinisikan yang konstan tetapi saya percaya tipe Enum jauh terbaik untuk tugas ini. Mereka dapat mewakili integer dan string untuk item dalam waktu yang sama, sekaligus menjaga kode Anda lebih mudah dibaca.
Enum diperkenalkan ke Python pada versi 3.4. Jika Anda menggunakan lebih rendah (seperti v2.x) Anda masih dapat memilikinya dengan menginstal paket backported :
pip install enum34
.Ini cukup banyak. Anda dapat mewarisi
ChoiceEnum
untuk membuat definisi Anda sendiri dan menggunakannya dalam definisi model seperti:Kueri adalah lapisan gula pada kue karena Anda mungkin menebak:
Mewakili mereka dalam string juga menjadi mudah:
sumber
ChoiceEnum
, Anda dapat menggunakan.value
dan.name
seperti yang dijelaskan @kirpit dan mengganti penggunaanchoices()
dengan -tuple([(x.value, x.name) for x in cls])
baik dalam fungsi (KERING) atau langsung di konstruktor bidang.Gunakan seperti ini:
sumber
Pada Django 3.0, Anda dapat menggunakan:
sumber
Cukup ganti nomor Anda dengan nilai yang dapat dibaca manusia yang Anda inginkan. Dengan demikian:
Ini membuatnya dapat dibaca manusia, namun, Anda harus menentukan pemesanan Anda sendiri.
sumber
Jawaban saya sangat terlambat dan mungkin tampak jelas bagi para ahli-Django saat ini, tetapi bagi siapa pun yang mendarat di sini, saya baru-baru ini menemukan solusi yang sangat elegan yang dibawa oleh django-model-utils: https://django-model-utils.readthedocs.io/ en / latest / utilities.html # choices
Paket ini memungkinkan Anda untuk menentukan Pilihan dengan tiga tupel di mana:
Jadi, inilah yang dapat Anda lakukan:
Cara ini:
Nikmati :)
sumber
priority = models.IntegerField(default=PRIORITIES.Low, choices=PRIORITIES)
(tentu saja, penugasan prioritas harus diindentasi agar berada di dalam kelas Thing untuk melakukannya). Juga pertimbangkan untuk menggunakan kata / karakter huruf kecil untuk pengenal python, karena Anda tidak merujuk ke kelas, tetapi sebagai gantinya parameter (Pilihan Anda akan menjadi:(0, 'low', 'Low'),
dan seterusnya).Awalnya saya menggunakan versi modifikasi dari jawaban @ Allan:
Disederhanakan dengan
django-enumfields
paket paket yang sekarang saya gunakan:sumber
Opsi pilihan model menerima urutan yang terdiri dari iterabel tepat dua item (misalnya [(A, B), (A, B) ...]) untuk digunakan sebagai pilihan untuk bidang ini.
Sebagai tambahan, Django menyediakan tipe pencacahan yang Anda dapat subkelas untuk mendefinisikan pilihan dengan cara yang ringkas:
Django mendukung penambahan nilai string ekstra ke akhir tupel ini untuk digunakan sebagai nama, atau label yang bisa dibaca manusia. Label dapat berupa string yang dapat diterjemahkan dengan malas.
Catatan: Anda dapat menggunakan menggunakan
ThingPriority.HIGH
,ThingPriority.['HIGH']
atauThingPriority(0)
untuk mengakses atau anggota enum lookup.sumber