Model¶
Sebuah model adalah tunggal, sumber pasti dari informasi tentang data anda. Itu mengandung bidang-bdiang penting dan perilaku dari data anda masih sedang menyimpan. Umumnya, stiap model memetakan pada sebuah tabel basisdata tunggal.
Dasar:
Setiap model adalah kelas Python yang subkelas
django.db.models.Model
.Setiap atribut dari model mewakili bidang basisdata.
Dengan semua ini, Django memberikan API akses-basisdata dibangkitkan-otomatis; lihat Membuat query.
Contoh cepat¶
Model contoh ini menentukan Person
, yang mempunyai first_name
dan last_name
:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_name
dan last_name
adalah fields dari model. Setiap bidang ditentukan sebagai atribut kelas, dan setiap atribut memetakan pada sebuah kolom basisdata.
Model Person
diatas akan membuat sebuah tabel basisdata seperti ini:
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
Beberapa catatan teknis:
Nama dari tabel,
myapp_person
, otomatis berasal dari beberapa metadata model tetapi dapat ditimpa. Lihat Nama tabel untuk rincian lebih.Sebuah bidang
id
ditambahkan secara otomatis, tetapi perilaku ini dapat dikesampingkan. Lihat Bidang primary key otomatis.SQL
CREATE TABLE
dalam contoh ini dibentuk menggunakan sintaksis PostgreSQL, tetapi itu perlu dicatat Django menggunakan SQL disesuaikan pada backend basisdata ditentukan dalam settings file anda.
Menggunakan model¶
Sekali anda telah menentukan model anda, anda butuh memberitahu Django anda sedang akan menggunakan model-model tersebut. Lakukan ini dengan menyunting berkas pengaturan anda dan merubah pengaturan INSTALLED_APPS
untuk menambah nama dari modul yang mengandung models.py
anda.
Sebagai contoh, jika model-model untuk aplikasi anda tinggal dalam modul myapp.models
(struktur paket yang dibuat untuk sebuah aplikasi oleh tulisan manage.py startapp
), INSTALLED_APPS
harus membaca, dalam bagian:
INSTALLED_APPS = [
#...
'myapp',
#...
]
Ketika anda menambah aplikasi baru pada INSTALLED_APPS
, pastikan menjalankan manage.py migrate
, pilihannya membuat perpindahan untuk mereka dahulu dengan manage.py makemigrations
.
Bidang¶
Bagian paling penting dari sebuah model – dan hanya membutuhkan bagian dari sebah model – adalah daftar bidang basisdata itu tentukan. Bidang-bidang ditentukan oleh atribut kelas. Hati-hati tidak memilih nama bidang yang bertentangan dengan models API seperti clean
, save
, atau delete
.
Contoh:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
Jenis bidang¶
Setiap bidang dalam model anda harus berupa sebuah instance dari kelas Field
sesuai. Django menggunakan jenis kelas bidang untuk menentukan sedikit hal:
Jenis kolom, yang memberitahu basisdata maca apa dari data disimpan (sebagai contoh
INTEGER
,VARCHAR
,TEXT
).HTML awalan widget untuk digunakan ketika membangun sebuah bidang formulir (sebagai contoh
<input type="text">
,<select>
).Persyaratan pengesahan minimal, digunakan di admin Django dan di formulir dibangkitkan-otomatis.
Django dibekali dengan lusinan dari jenis-jenis siap pakai; anda dapat menemukan daftar lengkap dalam model field reference. Anda dapat dengan mudah menulis bidang-bidang anda sendiri jika satu siap-pakai Django tidak melakukan trik; lihat Menulis bidang model penyesuaian.
Pilihan bidang¶
Setiap bidang-bidang mengambil kumpulan tertentu dari argumen bidang-tertentu (didokumentasikan dalam model field reference). Sebagai contoh, CharField
(dan subkelasnya) membutuhkan sebuah argumen max_length
yang menentukan ukuran dari bidang basisdata VARCHAR
digunakan untuk menyimpan data.
Ada juga sekumpulan dari argumen umum tersedia pada semua jenis bidang. Semua adalah pilihan. Mereka sepenuhnya dijelaskan dalam reference, tetapi ini adalah ringkasan cepat dari satu kebanyakan sering-digunakan:
null
Jika
True
, Django akan menyimpan nilai-nilai kosong sebagaiNULL
di basisdata. Awalan adalahFalse
.blank
Jika
True
, bidang diizinkan menjadi kosong. Awalan adalahFalse
.Catat bahwa ini berbeda dari
null
.blank
adalah pengesahan-terkait. Jika sebuah bidang mempunyaiblank=True
, pengesahan formulir akan mengizinkan masukan dari sebuah nilai kosong. Jika sebuah bidang mempunyaiblank=False
, bidang akan diwajibkan.choices
Sebuah perulangan (yaitu, sebuah daftar atau tuple) dari 2-tuple digunakan sebagai pilihan untuk bidang ini. Jika ini diberikan, widget formulir awalan akan berupa kotak pilih daripada bidang teks standar dan akan membatasi pilihan pada pilihan diberikan.
Daftar pilihan kelihatan seperti ini:
YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), )
Unsur pertama dalam setiap tuple adalah nilai yang akan disimpan dalam basisdata. Unsur kedua akan diperlihatkan oleh widget formulir awalan atau dalam sebuah
ModelChoiceField
. Memberikan sebuah instance model, nilai diperlihatkan untuk bidang pilihan dapat diakses menggunakan metodeget_FOO_display()
. Sebagai contoh:from django.db import models class Person(models.Model): SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() 'Large'
default
Nilai awalan untuk bidang. Ini dapat berupa nilai atau obyek callable. Jika callable itu akan diapnggil setiap waktu obyek baru dibuat.
help_text
Teks “help” tambahan untuk ditampilkan dengan widget formulir. Itu sangat berguna untuk dokumentasi bahkan jika bidang anda tidak digunakan pada formulir.
primary_key
Jika
True
, bidang ini adalah primary key untuk model.Jika anda tidak menentukan
primary_key=True
untuk tiap bidang di model anda, Django akan otomatis menambahkan sebuahIntegerField
untuk menahan primary key, jadi anda tidak butuh menyetelprimary_key=True
pada tiap bidang anda meskipun anda ingin menimpa kebiasaan primary-key awalan. Untuk lebih, lihat Bidang primary key otomatis.Bidang kunci utama adalah hanya-baca. Jika anda merubah nilai dari primaru key pada sebuah obyek yang ada dan kemudian menyimpan itu, sebuah obyek baru akan dibuat bersama satu yang lama. Sebagai contoh:
from django.db import models class Fruit(models.Model): name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple') >>> fruit.name = 'Pear' >>> fruit.save() >>> Fruit.objects.values_list('name', flat=True) ['Apple', 'Pear']
unique
Jika
True
, bidang ini harus unik diseluruh tabel.
Lagi, ini hanya gambaran pendek dari kebanyakan pilihan bidang umum. Rincian penuh dapat ditemukan di common model field option reference.
Bidang primary key otomatis¶
Secara awal, Django memberikan setiap model bidang berikut:
id = models.AutoField(primary_key=True)
Ini adalah primary key peningkatan-otomatis.
Jika anda suka menentukan primary key penyesuaian, cukup tentukan primary_key=True
pada satu dari bidang-bdiang anda. Jika Django melihat anda telah jelas menyetel Field.primary_key
, itu tidak akan menambahkan kolom id
otomatis.
Setiap model membutuhkan setidaknya satu bidang untuk memiliki primary_key=True
(antara dinyatakan jelas atau ditambahkan otomatis).
Nama-nama bidang bertele-tele¶
Setiap jenis bidang, kecuali untuk ForeignKey
, ManyToManyField
dan OneToOneField
, mengambil sebuah pilihan argumen penempatan pertama – sebuah nama bertele-tele. Jika nama bertele-tele tidak diberikan, DJango akan otomatis membuat itu menggunakan nama atribut bidang, merubah garis bawah menjadi ruang.
Dalam contoh ini, nama bertele-tele adalah "person's first name"
:
first_name = models.CharField("person's first name", max_length=30)
Dalam contoh ini, nama bertele-tele adalah "first name"
:
first_name = models.CharField(max_length=30)
ForeignKey
, ManyToManyField
dan OneToOneField
membutuhkan argumen pertama untuk jadi kelas model, jadi gunakan argumen kata kunci verbose_name
:
poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)
Kebiasaan tidak menghuruf besarkan huruf pertama dari verbose_name
. Django akan otomatis menghuruf besarkan huruf pertama dimana itu dibutuhkan.
Hubungan¶
Jelas, kekuatan dari hubungan basisdata bergantung dalam tabel berkaitan ke setiap lainnya. Django menawarkan cara menentukan tiga jenis paling umum dari hubungan basisdata: many-to-one, many-to-many dan one-to-one.
Hubungan banyak-ke-satu¶
Untuk menentukan hubungan many-to-one, gunakan ForeignKey
. Anda menggunakan itu seperti jenis Field
lainnya: dengan menyertakan itu sebagai sebuah atribut kelas dari model anda.
ForeignKey
membutuhkan sebuah argumen penempatan: kelas dimana model terkait.
Sebagai contoh, jika sebuah model Car
mempunyai Manufacturer
– yaitu, Manufacturer
membuat banyak mobil tetapi setiap car
hanya mempunyai satu Manufacturer
– gunakan pengertian berikut:
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...
Anda dapat juga membuat recursive relationships (sebuah obyek dengan hubungan many-to-one ke diri sendiri) dan relationships to models not yet defined; lihat the model field reference untuk rincian.
Disarankan, tetapi tidak wajib, bahwa nama dari bidang ForeignKey
(manufacturer
dalam contoh diatas) menjadi nama dari model, huruf kecil. Anda dapat, tentu saja, memanggil bidang apapun kamu ingin. Sebagai contoh:
class Car(models.Model):
company_that_makes_it = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
)
# ...
lihat juga
Bidang ForeignKey
menerima sejumlah dari argumen tambahan yang dijelaskan dalam the model field reference. Pilihan-pilihan ini membantu menentukan bagaimana hubungan harus bekerja; semua adalah pilihan.
Untuk rincian pada mengakses obyek terkait-kebelakang, lihat Following relationships backward example.
Untuk kode contoh, lihat Many-to-one relationship model example.
Hubungan banyak-ke-banyak¶
Untuk menentukan hubungan many-to-many, gunakan ManyToManyField
. Anda menggunakan itu seperti jenis Field
lainnya: dengan menyertakan itu sebagai sebuah atribut kelas dari model anda.
ManyToManyField
membutuhkan argumen penempatan: kelas pada yang model yang terkait.
Sebagai contoh, jika Pizza
mempunyai banyak obyek Topping
–yaitu, sebuah Topping
dapat berupa pada banyak pizza dan setiap Pizza
mempunyai banyak taburan – ini adalah bagaimana anda mewakili itu:
from django.db import models
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
Seperti ForeignKey
, anda dapat juga membuat recursive relationships (sebuah obyek dengan hubungan many-to-many ke itu sendiri) dan relationships to models not yet defined.
Disarankan, tetapi tidak wajib, bahwa nama dari sebuah ManyToManyField
(toppings
dalam contoh diatas) menjadi plural menggambarkan kumpulan dari obyek model terkait.
Itu tidak masalah model mana mempunyai ManyToManyField
, tetapi anda harus menaruh itu dalam satu dari model - tidak keduanya.
Umumnya, instance ManyToManyField
harus pergi ke obyek yang akan disunting pada sebuah formulir. Dalam contoh diatas, toppings``berada dalam ``Pizza
(daripada toppings
memiliki Pizza
ManyToManyField
) karena itu lebih alami untuk berpikir tentang sebuah pizza mempunyai taburan berada pada banyak pizza. Cara itu menyetel diatas, formulir Pizza
akan membiarkan pengguna memilih taburan.
lihat juga
Lihat Many-to-many relationship model example untuk contoh penuh.
Bidang ManyToManyField
juga menerima sejumlah dari argumen tambahan yang dijelaskan dalam the model field reference. Pilihan-pilihan ini membantu menentukan bagaimana hubungan harus bekerja; semua adalah pilihan.
Bidang tambahan pada hubungan many-to-many¶
Jika anda hanya berurusan dengan hubungan many-to-many sederhana seperti mixin dan mencocokkan pizza dan taburan, sebuah ManyToManyField
standar adalah semua yang anda butuhkan. Bagaimanapun, terkadang anda mungkin butuh mengkaitkan data dengan hubungan diantara dua model.
Sebagai contoh, pertimbangkan kasus dari sebuah aplikasi melacak kelompok musikal yang milik pemusik. Ada hubungan many-to-many diantara seorang dan kelompok yang mereka adalah anggota, jadi anda dapat menggunakan sebuah ManyToManyField
untuk mewakili hubungan ini. Bagaimanapun, ada banyak dari rincian tentang keanggotaan yang mungkin ingin dikumpulkan, seperti tanggal dimana seseorang bergabung kelompok.
Untuk keadaan ini, Django mengizinkan anda menentukan model yang akan digunakan untuk menentukan hubungan many-to-many. Anda dapat kemudian menaruh bidang-bidang tambahan pada model menengah. Model menengah dikaitkan dengan ManyToManyField
menggunakan argumen through
untuk menunjuk model yang akan bertindak sebagai sebuah perantara. Untuk contoh pemusik kami, kode akan terlihat sesuatu seperti ini:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Ketika anda menyetel model perantara, anda jelas menentukan foreign key pada model-model yang terlibat dalam hubungan many-to-many. Pernyataan jelas ini menentukan bagaimana dua model terkait.
Ada beberapa batasan pada model menengah:
Model perantara anda harus mengandung satu - dan *hanya` satu - foreign key pada model sumber (ini akan berupa
Group
dalam contoh kami), atau anda harus menentukan jelas foreign key Django harus gunakan untuk hubungan menggunakanManyToManyField.through_fields
. Jika anda mempunyai lebih dari satu foreign key danthrough_fields
tidak ditentukan, kesalahan pengesahan akan dimunculkan. Pembatasan yang mirip berlaku pada foreign key ke model sasaran (ini akan berupaPerson
dalam contoh kami).Untuk sebuah model yang mempunyai hubungan many-to-many ke itu sendiri melalui sebuah model perantara, dua foreign key pada model sama diizinkan, tetapi mereka akan diperlakukan sebagai dua sisi (berbeda) dari hubungan many-to-many. Jika ada lebih dari dua foreign key, anda harus juga menentukan
through_fields
seperti diatas, atau sebuah kesalahan pengesahan akan dimunculkan.Ketika menentukan hubungan many-to-many dari model kepada itu sendiri, menggunakan model perantara, anda harus menggunakan
symmetrical=False
(lihat the model field reference).
Sekarang yang anda telah menyetel ManyToManyField
anda untuk menggunakan model pertengangan kami (Membership
, dalam kasus ini), anda siap mulai membuat beberapa hubungan many-to-many. Anda melakukan ini dengan membuat instance-instance dari model pertengahan:
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
Tidak seperti bidang many-to-many biasa, anda tidak dapat menggunakan add()
, create()
, atau set()
untuk membuat hubungan:
>>> # The following statements will not work
>>> beatles.members.add(john)
>>> beatles.members.create(name="George Harrison")
>>> beatles.members.set([john, paul, ringo, george])
MEngapa? anda tidak dapat membuat sebuah hubungan diantara Person
dan Group
- anda butuh menentukan semua rincian untuk hubungan diwajibkan oleh model Membership
. Panggilan add
, create
dan penugasan tidak menyediakan sebuah cara untuk menentukan rincian tambahan ini. Sebagai sebuah hasil, mereka ditiadakan untuk hubungan many-to-many yang menggunakan sebuah model pertengahan. Cara satu-satunya untuk membuat jenis ini dari hubungan adalah membuat instance-instance dari model pertengahan.
Metode remove()
ditiadakan untuk alasan mirip. Sebagai contoh, jika penyesuaian melalui tabel ditentukan oleh model pertengahan tidak melaksanakan keunikan pada pasangan (model1, model2)
, panggilan remove()
tidak akan cukup menyediakan informasi untuk yang instance model pertengahan harus dihapus:
>>> Membership.objects.create(person=ringo, group=beatles,
... date_joined=date(1968, 9, 4),
... invite_reason="You've been gone for a month and we miss you.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]>
>>> # This will not work because it cannot tell which membership to remove
>>> beatles.members.remove(ringo)
Bagaimanapun, metode clear()
dapat digunakan untuk memindahkan semua hubungan many-to-many untuk sebuah contoh:
>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
<QuerySet []>
Sekali anda telah membangun hubungan many-to-many dengan membuat instance-instance dari model pertengahan anda, anda dapat menerbitkan permintaan-permintaan. Seperti dengan hubungan biasa many-to-many, anda dapat meminta menggunakan atribut-atribut dari model hubungan-many-to-many:
# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
<QuerySet [<Group: The Beatles>]>
Ketika anda sedang menggunakan model menengah, anda dapat juga meminta pada atributnya:
# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>
Jika anda butuh mengakses informasi keanggotaan anda mungkin melakukan itu dengan langsung meminta model Membership
:
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
cara lain mengakses informasi sama adalah dengan meminta many-to-many reverse relationship dari obyek Person
:
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
Hubungan satu-ke-satu¶
Untuk menentukan hubungan one-to-one, gunakan OneToOneField
. Anda dapat menggunakan itu hanya seperti jenis Field
lainnya: dengan menyertakan itu sebagai sebuah atribut kelas dari model anda.
Ini adalah paling berguna pada primaty key dari sebuah obyek ketika obyek itu “extends” obyek lain di beberapa cara.
OneToOneField
membutuhkan argumen penempatan: kelas dimana model yang terkait.
Sebagai contoh, jika anda sedang membangun sebuah basisdata dari “places”, anda akan membangun hal yang cukup standar seperti alamat, nomor telepon, dll dalam basisdata. Kemudian, jika anda ingin membangun sebuah basisdata restoran di atas tempat-tempat, daripada mengulangi anda sendiri dan menggandakan bidang-bidang tersebut dalam model Restaurant
, anda dapat membuat Restaurant
memiliki kelas OneToOneField
pada Place
(karena sebuah restauran “adalah sebuah” tempat; faktanya, untuk menangani ini anda biasanya menggunakan inheritance, yang melibatkan sebuah hubungan jelas one-to-one.
Seperti ForeignKey
, recursive relationship dapat ditentukan dan references to as-yet undefined models dapat dibuat.
lihat juga
Lihat One-to-one relationship model example untuk contoh penuh.
Bidang OneToOneField
juga menerima sebuah argumen pilihan parent_link
.
OneToOneField
digunakan untuk otomatis menjadi primary key pada model. Ini tidak lagi benar (meskipun anda dapat manual melewatkan dalam argumen primary_key
jika anda suka). Dengan demikian, itu sekarang memungkinkan memiliki banyak bidang dari jenis OneToOneField
pada model tunggal.
Model-model lintas berkas-berkas¶
Ini sangat OKE untuk menghubungkan model ke satu dari aplikasi lain. Untuk melakukan ini, impor model terkait pada atas dari berkas dimana model anda ditentukan. Kemudian, cukup mengacu ke kelas model lain dimana dibutuhkan. Sebagai contoh:
from django.db import models
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
Batasan bidang nama¶
Django menempatkan hanya dua batasan pada model nama bidang:
Sebuah nama bidang tidak dapat berupa sebuah kata cadangan Python, karena itu akan menghasilkan dalam kesalahan sintaksis. Sebagai contoh:
class Example(models.Model): pass = models.IntegerField() # 'pass' is a reserved word!
Sebuah nama bidang tidak dapat mengandung lebih dari satu garis bawah dalam sebuah baris, karena cara bekerja sintaksis pencarian permintaan Django. Sebagai contoh:
class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
Batasan-batasan ini dapat dipecahkan, meskipun, karena nama bidang anda tidak butuh harus cocok nama kolom basisdata anda. Lihat pilihan db_column
.
Kata-kata pemesan SQL, seperti join
, where
atau select
, adalah diizinkan sebagai nama bidang model, karena Django meloloskan semua nama-nama tabel basisdata dan nama-nama kolom di setiap permintaan SQL pokok. Itu menggunakan sintaksis mengutip dari mesin basisdata tertentu anda.
Jenis bidang penyesuaian¶
Jika satu dari bidang-bidang model yang ada tidak dapat digunakan untuk memenuhi tujuan anda, atau jika anda berharap mengambil keuntungan dari beberapa jenis kolom basisdata kurang umum, anda dapat membuat kelas bidang anda sendiri. Cakupan penuh dari membuat bidang-bidang anda sendiri disediakan dalam Menulis bidang model penyesuaian.
Pilihan Meta
¶
Memberikan model anda metadata dengan menggunakan class Meta
sebelah dalam, seperti begitu:
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
Metadata model adalah “apapun yang bukan sebuah bidang”, seperti pilihan pengurutan (ordering
), nama tabel basisdata (db_table
), atau nama-nama tunggal dan jamal dapat-dibaca-manusia (verbose_name
dan verbose_name_plural
). Tidak satupun diwajibkan, dan menambahkan class Meta
pada sebauh model adalah sepenuhnya pilihan.
Daftar lengkap dar semua kemungkinan pilihan Meta
dapat ditemukan dalam model option reference.
Atribut model¶
objects
Atribut paling penting dari sebuah model adalah
Manager
. Itu adalah antarmuka melalui tindakan permintaan basisdata mana yang disediakan pada model-model dan digunakan pada retrieve the instances dari basisdata. Jika tidak ada penyesuaianManager
ditentukan, nama awalan adalahobjects
. Pengelola hanya dapat diakses melalui kelas-kelas model, bukan instance-instance model.
Cara model¶
Tentukan metode penyesuaian pada sebuah model untuk menambah fungsionalitas “tingkat-baris” pada obyek-obyek anda. Sedangkan metode Manager
dimaksudkan melakukan hal-hal “lebar-tabel”, metode model harus bertindak pada instance model tertentu.
Ini adalah teknik bernilai untuk menjaga logika bisnis dalam satu tempat – model.
Sebagai contoh, model ini mempunyai beberapa cara penyesuaian:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
def _get_full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)
Cara terakhir di contoh ini adalah property.
model instance reference mempunyai daftar lengkap dari methods automatically given to each model. Anda dapat menimpa kebanyakan dari ini – lihat overriding predefined model methods, dibawah – tetapi ada sepasang yang anda akan hampir selalu ingin tentukan:
__str__()
(Python 3)“metode ajaib” Python yang mengembalikan sebuah unicode “perwakilan” dari obyek. Ini adalah apa Python dan Django akan gunakan kapanpun sebauh instance model butuh dipaksa dan ditambilkan sebagai string polos. Terutama, ini terjadi ketika anda memperlihatkan sebuah obyek dalam sebuah konsol interaktif atau dalam admin.
Anda akan selalu ingin menentukan cara ini; cara awal tidak membantu sama sekali.
__unicode__()
(Python 2)- Python 2 equivalent of
__str__()
. get_absolute_url()
Ini memberitahu Django bagaimana menghitung URL untuk sebuah obyek. Django menggunakan ini dalam antarmuka adminnya, dan kapan pun itu butuh mencari tahu untuk sebuah obyek.
Obyek apapun yang mempunyai sebuah URL yang unik mencirikan itu harus menentukan metode ini.
Menimpa metode model yang detetapkan¶
Ada kumpulan lain dari model methods yang mengenkapsulasi sekolompok perilaku basisdata yang anda akan ingin sesuaikan. Khususnya anda akan sering ingin dirubah merubah cara save()
dan delete()
bekerja.
Anda bebas untuk mengesampingkan cara ini (dan cara model lainnya) untuk merubah kebiasaan.
Sebuah penggunaan-kasus klasik untuk menimpa metode-metode siap pakai jika anda ingin sesuatu terjadi ketika anda menyimpan sebuah obyek. Sebagai contoh (lihat save()
untuk dokumentasi dari parameter-parameter itu terima):
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
Anda dapat juga mencegah mengatakan:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
if self.name == "Yoko Ono's blog":
return # Yoko shall never have her own blog!
else:
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
Itu adalah penting mengingat untuk memanggil metode super kelas – yaitu bahwa bisnis super(Blog, self).save(*args, **kwargs)
– untuk memastikan bahwa obyek masih disimpan kedalam basisdata. jika anda lupa untuk memanggil metode super kelas, perilaku awalan tidak akan terjadi dan basisdata tidak disentuh.
Itu juga penting bahwa anda melewati argumen yang dapat diloloskan ke metode model – yaitu apa *args, **kwargs
sedikit lakukan, Django akan, dari waktu ke waktu, memperpanjang kemampuan metode model siap-pakai, menambahkan argumen-argumen baru. Jika anda menggunakan *args, **kwargs
dalam pengertian metode anda, anda dijamin bahwa kode anda akan otomatis mendukung argumen-argumen tersebut ketika mereka ditambahkan.
Menimpa metode-metode model tidak dipanggil pada tindakan massal
Catat bahwa metode delete()
untuk sebuah obyej tidak dibutuhkan dipanggil ketika deleting objects in bulk using a QuerySet atau sebagai sebuah hasil dari sebuah cascading delete
. Untuk memastikan penyesuaian logika hapus dijalankan, anda dapat menggunakan sinyal pre_delete
dan/atau post_delete
.
Sayangnya tidak ada pemecahan ketika obyek creating
atau updating
dalam jumlah besar, sejak tidak satupun dari save()
, pre_save
, dan post_save
dipanggil.
Menjalankan penyesuaian SQL¶
Pola umum lain sdang menulis pernyataan SQL penyesuaian dalam metode-metode model dan metode-metode tingkat-modul. Untuk rincian lebih pada menggunakan SQL mentah, lihat dokumentasi pada using raw SQL.
Model warisan¶
Warisan model dalam Django bekerja hampir sama pada cara biasa warisan kelas bekerja dalam Python, tetapi dasar-dasar pada permulaan dari halaman harus masih diikuti. Itu berarti kelas dasar harus mensubkelaskan django.db.models.Model
.
Satu-satunya keputusan yang anda punya untuk membuat apakah anda ingin model-model induk menjadi model-model dalam hak mereka sendiri (dengan tabel-tabel basisdata mereka sendiri), atau jika induk hanya menampung dari informasi umum yang akan hanya nampak melalui model-model anak.
Ada tiga gaya warisan yang mungkin di Django.
Sering, anda akan hanya ingin menggunakan kelas induk untuk menampung informasi yang anda tidak ingin miliki untuk mengetikkan setiap model anak. Kelas ini tidak akan pernah digunakan dalam pengasingan, jadi Kelas-kelas dasar abstrak adalah apa yang anda kejar.
Jika anda sedang mensubkelaskan sebuah model yang ada (mungkin sesuatu dari aplikasi lain seluruhnya) dan ingin setiap model memiliki tabel basisdata itu sendiri, Warisan banyak-tabel adalah cara untuk pergi.
Akhirnya, jika anda hanya ingin merubah perilaku tingkat-Python dari sebuah model, tanpa merubah bidang-bidang model dalam cara apapun, anda dapat menggunakan Model proxy.
Kelas-kelas dasar abstrak¶
Kelas-kelas dasar abstrak berguna ketika anda ingin menaruh beberapa informasi umum kedalam sejumlah model-model lain. Anda menulis kelas dasar anda dan menaruh abstract=True
dalam kelas Meta. Model ini kemudian tidak digunakan untuk membuat tabel basisdata apapun. Malahan, ketika itu digunakan sebagai kelas dasar untuk model-model lain, bidangnya akan ditambahkan ke kelas anak mereka. Itu adalah sebuah kesalahan memiliki bidang-bidang dalam kelas dasar abstrak dengan nama sama sepertimereka dalam anak (dan Django akan memunculkan sebuah pengecualian).
Sebuah contoh:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
Model Student
akan mempunyai tiga bidang: name
, age
dan home_group
. Model CommonInfo
tidak dapat digunakan sebagai model Django biasa, sejak itu adalah sebuah kelas dasar abstrak. Itu tidak membangkitkan sebuah tabel basisdata atau mempunyai sebuah pengelola, dan tidak dapat di instansiasikan atau disimpan langsung.
Untuk banyak penggunaan, jenis ini dari warisan model akan tepatnya apa yang anda inginkan. Itu menyediakan sebuah cara untuk faktor luar informasi umum pada tingkat Python, selagi masih hanya membuat satu tabel basisdata per model anak pada tingkat basisdata.
Meta
warisan¶
Ketika sebuah kelas dasar abstrak dibuat, Django membuat kelas sebelah dalam Meta apapun anda nyatakan di kelas dasar tersedia sebagai sebuah atribut. Jika sebuah kelas anak tidak menyatakan kelas Meta nya sendiri, itu akan mewarisi Meta induk. Jika anak ingin memperpanjang kelas Meta induk, itu dapat mensubkelaskan itu. Sebagai contoh:
from django.db import models
class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
Django membuat satu penyesuaian pada kelas Meta dari kelas dasar abstrak: sebelum memasang atribut Meta, itu menyetel abstract=False
. Ini berarti bahwa anak dari kelas-kelas dasar abstrak tidak otomatis menjadi kelas-kelas abstrak mereka sendiri. Tentu saja, anda dapat membuat sebuah kelas dasar abstrak yang mewarisi dari kelas dasar abstrak lain. Anda hanya butuh mengingat untuk menjelaskan menyetel abstract=True
setiap kali.
Beberapa atribut tidak akan masuk akal untuk disertakan dalam kelas Meta dari sebuah kelas dasar abstrak. Sebagai coontoh, menyertakan db_table
akan berarti bahwa semua kelas-kelas anak (satu yang tidak menentukan milik mereka Meta) akan menggunakan tabel basisdata sama, yang hampir pasti bukan yang anda inginkan.
Warisan banyak-tabel¶
Jenis kedua dari warisan model didukung oleh Django adalah ketika setiap model dalam hirarki adalah sebuah model semua oleh itu sendiri. Setiap model berhubungan ke tabel basisdata itu sendiri dan dapat diminta dan dibuat sendiri-sendiri. Hubungan warisan memperkenalkan tautan diantara model anak dan setiap dari induknya (melalui dibuat-otomatis OneToOneField
). Sebagai contoh:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Semua dari bidang-bidang dari Place
akan juga tersedia dalam Restaurant
, meskipun data akan tinggal dalam tabel basisdata berbeda. Jadi kedua ini memungkinkan:
>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
Jika anda mempunyai sebuah Place
yang juga sebuah Restaurant
, anda dapat ambil dari obyek Place
ke obyek Restaurant
dengan menggunakan versi huruf-kecil dari nama model:
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>
Bagaimanapun, jika p
dalam contoh-contoh diatas bukan sebuah Restaurant
(itu telah dibuat langsung sebagai sebuah obyek Place
atau induk dari beberapa kelas lain(, mengacu pada p.restaurant
akan memunculkan sebuah pengecualian Restaurant.DoesNotExist
.
Meta
dan warisan banyak-tabel¶
Dalam keadaan warisan banyak-tabel, itu tidak masuk akal untuk sebuah kelas anak mewarisi dari kelas Meta induknya. Semua pilihan Meta telah diberlakukan ke kelas induk dan memberlakukan mereka kembali akan biasanya hanya membawa ke perilaku bertentangan (ini adalah berlawanan dengan kasus kelas dasar abstrak, dimana kelas dasar tidak ada dalam hak itu sendiri).
Jadi sebuah model anak tidak mempunyai akses ke kelas Meta induknya. Bagaimanapun, ada sedikit kasus terbatas ketika anak mewarisi perilaku dari induk: jika anak tidak menentukan sebuah atribut ordering
atau sebuah atribut get_latest_by
, itu akan mewarisi ini dari induknya.
Jika induk mempunyai sebuah pengurutan dan anda tidak ingin anak mempunyai pengurutan alami, anda dapat jelas meniadakan itu:
class ChildModel(ParentModel):
# ...
class Meta:
# Remove parent's ordering effect
ordering = []
Mewarisi dan membalikkan hubungan¶
Karena warisan banyak-tabel menggunakan sebuah OneToOneField
ersirat pada tautan anak dan induk, itu memungkinkan memindahkan dari induk turun ke anak, seperti dalam contoh diatas. Bagaimanapun, ini menggunakan nama yang nilai related_name
awalannya untuk hubungan ForeignKey
dan ManyToManyField
. Jika anda sedang menaruh jenis itu dari hubungan pada sebuah subkelas dari model induk, anda harus menentukan atribut related_name
pada setiap bidang itu. Jika anda lupa, Django akan memunculkan sebuah kesalahan pengesahan.
Sebagai contoh, menggunakan kelas Place
diatas lagi, mari kita membuat subkelas lain dengan sebuah ManyToManyField
:
class Supplier(Place):
customers = models.ManyToManyField(Place)
Ini hasil di kesalahan:
Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.
HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.
Menambahkan related_name
ke bidang customers
seperti berikut akan menyelesaikan kesalahan: models.ManyToManyField(Place, related_name='provider')
.
Menentukan bidang tautan induk¶
Sebagai disebutkan, Django akan otomatis membuat sebuah OneToOneField
menghubungkan ke kelas anak anda kembali ke model induk bukan-abtrak apapun. Jika anda ingin mengendalikan nama dari atribut menghubungkan kembali ke induk, anda dapat membuat OneToOneField
anda sendiri dan menyetel parent_link=True
untuk menunjukkan bahwa bidang anda menghubungkan kembali ke kelas induk.
Model proxy¶
Ketika menggunakan multi-table inheritance, tabel basisdata baru dibuat untuk setiap subkelas dari model. Ini biasanya keinginan kebiasaan, sejak subkelas butuh tempar menyimpan bidang data tambahan apapun yang tidak hadir pada kelas dasar. Terkadang, bagaimanapun, anda hanya ingin merubah kebiasaan Python dari model – mungkin merubah pengelola awalan, atau menambah metode baru.
This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.
Model proxy dinyatakan seperti model-model biasa. Anda memberitahu Django bahwa model proxynya dengan mengatur atribut proxy
dari kelas Meta
menjadi False
.
Sebagai contoh, misalnya anda ingin menambahkan sebuah metode ke model Person
. Anda dapat melakukannya seperti ini:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
Kelas MyPerson
berjalan pada tabel basisdata sama seperti induknya kelas Person
. Khususnya, instance baru apapun dari Person
akan juga diakses melalui MyPerson
, dan sebaliknya:
>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>
Anda dapat juga menggunakan sebuah model proxy untuk menentukan pengurutan awalan berbeda pada sebuah model. Anda mungkin tidak inging mengurutkan model Person
, tetapi umumnya pengurutan oleh atribut last_name
ketika anda menggunakan proxy. Ini adalah mudah:
class OrderedPerson(Person):
class Meta:
ordering = ["last_name"]
proxy = True
Sekarang permintaan Person
biasa akan tidak diurutkan dan permintaan OrderedPerson
akan diurutkan berdasarkan last_name
.
Model-model proxy mewarisi atribut Meta
in the same way as regular models.
QuerySet
masih mengembalikan model yang telah diminta¶
There is no way to have Django return, say, a MyPerson
object whenever you
query for Person
objects. A queryset for Person
objects will return
those types of objects. The whole point of proxy objects is that code relying
on the original Person
will use those and your own code can use the
extensions you included (that no other code is relying on anyway). It is not
a way to replace the Person
(or any other) model everywhere with something
of your own creation.
Batasan kelas dasar¶
A proxy model must inherit from exactly one non-abstract model class. You can’t inherit from multiple non-abstract models as the proxy model doesn’t provide any connection between the rows in the different database tables. A proxy model can inherit from any number of abstract model classes, providing they do not define any model fields. A proxy model may also inherit from any number of proxy models that share a common non-abstract parent class.
In earlier versions, a proxy model couldn’t inherit more than one proxy model that shared the same parent class.
Proxy model managers¶
If you don’t specify any model managers on a proxy model, it inherits the managers from its model parents. If you define a manager on the proxy model, it will become the default, although any managers defined on the parent classes will still be available.
Continuing our example from above, you could change the default manager used
when you query the Person
model like this:
from django.db import models
class NewManager(models.Manager):
# ...
pass
class MyPerson(Person):
objects = NewManager()
class Meta:
proxy = True
If you wanted to add a new manager to the Proxy, without replacing the existing default, you can use the techniques described in the custom manager documentation: create a base class containing the new managers and inherit that after the primary base class:
# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True
Anda mungkin tidak butuh melakukan ini terlalu sering, tetapi, ketika anda melakukan, sangat memungkinkan.
Differences between proxy inheritance and unmanaged models¶
Proxy model inheritance might look fairly similar to creating an unmanaged
model, using the managed
attribute on a
model’s Meta
class.
With careful setting of Meta.db_table
you could create an unmanaged model that
shadows an existing model and adds Python methods to it. However, that would be
very repetitive and fragile as you need to keep both copies synchronized if you
make any changes.
On the other hand, proxy models are intended to behave exactly like the model they are proxying for. They are always in sync with the parent model since they directly inherit its fields and managers.
Aturan-aturan umum adalah:
- If you are mirroring an existing model or database table and don’t want
all the original database table columns, use
Meta.managed=False
. That option is normally useful for modeling database views and tables not under the control of Django. - If you are wanting to change the Python-only behavior of a model, but
keep all the same fields as in the original, use
Meta.proxy=True
. This sets things up so that the proxy model is an exact copy of the storage structure of the original model when data is saved.
Banyak warisan¶
Just as with Python’s subclassing, it’s possible for a Django model to inherit from multiple parent models. Keep in mind that normal Python name resolution rules apply. The first base class that a particular name (e.g. Meta) appears in will be the one that is used; for example, this means that if multiple parents contain a Meta class, only the first one is going to be used, and all others will be ignored.
Umumnya, anda tidak akan butuh mewarisi banyak induk. Kasus-kegunaan utama dimana ini berguna adalah untuk kelas “mix-in”: menambahkan bidang ekstra tertentu atau metode pada setiap kelas yang mewarisi mix-in. Coba untuk menjaga hirarki warisan anda sesederhana dan semudah mungkin sehingga anda tidak harus berjuang bekerja diluar dimana potongan tertentu dari informasi berasal.
Note that inheriting from multiple models that have a common id
primary
key field will raise an error. To properly use multiple inheritance, you can
use an explicit AutoField
in the base models:
class Article(models.Model):
article_id = models.AutoField(primary_key=True)
...
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
...
class BookReview(Book, Article):
pass
Or use a common ancestor to hold the AutoField
:
class Piece(models.Model):
pass
class Article(Piece):
...
class Book(Piece):
...
class BookReview(Book, Article):
pass
Nama bidang “hiding” tidak diizinkan¶
In normal Python class inheritance, it is permissible for a child class to
override any attribute from the parent class. In Django, this isn’t usually
permitted for model fields. If a non-abstract model base class has a field
called author
, you can’t create another model field or define
an attribute called author
in any class that inherits from that base class.
This restriction doesn’t apply to model fields inherited from an abstract
model. Such fields may be overridden with another field or value, or be removed
by setting field_name = None
.
Kemampuan menimpa bidang-bidang abstrak telah ditambahkan.
Peringatan
Model managers are inherited from abstract base classes. Overriding an
inherited field which is referenced by an inherited
Manager
may cause subtle bugs. See custom
managers and model inheritance.
Catatan
Some fields define extra attributes on the model, e.g. a
ForeignKey
defines an extra attribute with
_id
appended to the field name, as well as related_name
and
related_query_name
on the foreign model.
These extra attributes cannot be overridden unless the field that defines it is changed or removed so that it no longer defines the extra attribute.
Overriding fields in a parent model leads to difficulties in areas such as
initializing new instances (specifying which field is being initialized in
Model.__init__
) and serialization. These are features which normal Python
class inheritance doesn’t have to deal with in quite the same way, so the
difference between Django model inheritance and Python class inheritance isn’t
arbitrary.
This restriction only applies to attributes which are
Field
instances. Normal Python attributes
can be overridden if you wish. It also only applies to the name of the
attribute as Python sees it: if you are manually specifying the database
column name, you can have the same column name appearing in both a child and
an ancestor model for multi-table inheritance (they are columns in two
different database tables).
Django akan memunculkan sebuah FieldError
jika anda menimpa bidang model apapun dalam model pendahulu apapun.
Mengorganisasikan model-model dalam sebuah paket¶
The manage.py startapp
command creates an application
structure that includes a models.py
file. If you have many models,
organizing them in separate files may be useful.
To do so, create a models
package. Remove models.py
and create a
myapp/models/
directory with an __init__.py
file and the files to
store your models. You must import the models in the __init__.py
file.
For example, if you had organic.py
and synthetic.py
in the models
directory:
from .organic import Person
from .synthetic import Robot
Explicitly importing each model rather than using from .models import *
has the advantages of not cluttering the namespace, making code more readable,
and keeping code analysis tools useful.
lihat juga
- Acuan Model
- Covers all the model related APIs including model fields, related
objects, and
QuerySet
.