Jawaban:
Berhati-hatilah untuk menyadari bahwa ada beberapa perbedaan antara OneToOneField(SomeModel)dan ForeignKey(SomeModel, unique=True). Sebagaimana dinyatakan dalam The Definitive Guide to Django :
OneToOneField
Hubungan satu-ke-satu. Secara konseptual, ini mirip dengan
ForeignKeydenganunique=True, tetapi sisi "terbalik" dari relasi akan langsung mengembalikan satu objek.
Berbeda dengan OneToOneFieldrelasi "mundur", relasi ForeignKey"terbalik" mengembalikan a QuerySet.
Misalnya, jika kita memiliki dua model berikut (kode model lengkap di bawah):
Car menggunakan model OneToOneField(Engine)Car2 menggunakan model ForeignKey(Engine2, unique=True)Dari dalam python manage.py shelljalankan yang berikut:
OneToOneField Contoh>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKeydengan unique=TrueContoh>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()
[<Car2: Mazda>]
from django.db import models
class Engine(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=25)
engine = models.OneToOneField(Engine)
def __unicode__(self):
return self.name
class Engine2(models.Model):
name = models.CharField(max_length=25)
def __unicode__(self):
return self.name
class Car2(models.Model):
name = models.CharField(max_length=25)
engine = models.ForeignKey(Engine2, unique=True, on_delete=models.CASCADE)
def __unicode__(self):
return self.name
e.carjuga berfungsi?
ForeignKeydengan unique=Truebukan OneToOneField? Saya melihat dalam pertanyaan-pertanyaan lain bahwa Django bahkan memperingatkan bahwa OneToOneFieldkepentingan yang biasanya terbaik adalah kepentingan seseorang. Kebalikannya QuerySettidak akan pernah memiliki lebih dari satu elemen, kan?
ForeignKey adalah untuk satu-ke-banyak, jadi objek Mobil mungkin memiliki banyak Roda, setiap Roda memiliki ForeignKey untuk Mobil miliknya. OneToOneField akan seperti Engine, di mana objek Mobil dapat memiliki satu dan hanya satu.
Cara terbaik dan paling efektif untuk mempelajari hal-hal baru adalah dengan melihat dan mempelajari contoh-contoh praktis dunia nyata. Misalkan sesaat Anda ingin membangun blog di Django di mana wartawan dapat menulis dan menerbitkan artikel berita. Pemilik surat kabar online ingin mengizinkan masing-masing reporternya menerbitkan sebanyak mungkin artikel yang mereka inginkan, tetapi tidak ingin reporter yang berbeda mengerjakan artikel yang sama. Ini berarti bahwa ketika pembaca pergi dan membaca artikel mereka hanya akan melihat satu penulis dalam artikel tersebut.
Misalnya: Artikel oleh John, Artikel oleh Harry, Artikel oleh Rick. Anda tidak dapat memiliki Artikel oleh Harry & Rick karena bos tidak ingin dua atau lebih penulis mengerjakan artikel yang sama.
Bagaimana kita bisa memecahkan 'masalah' ini dengan bantuan Django? Kunci untuk pemecahan masalah ini adalah Django ForeignKey.
Berikut ini adalah kode lengkap yang dapat digunakan untuk menerapkan gagasan bos kami.
from django.db import models
# Create your models here.
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
def __unicode__(self):
return self.first_name
class Article(models.Model):
title = models.CharField(max_length=100)
reporter = models.ForeignKey(Reporter)
def __unicode__(self):
return self.title
Jalankan python manage.py syncdbuntuk mengeksekusi kode sql dan membangun tabel untuk aplikasi Anda di database Anda. Kemudian gunakan python manage.py shelluntuk membuka shell python.
Buat objek Reporter R1.
In [49]: from thepub.models import Reporter, Article
In [50]: R1 = Reporter(first_name='Rick')
In [51]: R1.save()
Buat objek Artikel A1.
In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)
In [6]: A1.save()
Kemudian gunakan potongan kode berikut untuk mendapatkan nama reporter.
In [8]: A1.reporter.first_name
Out[8]: 'Rick'
Sekarang buat objek Reporter R2 dengan menjalankan kode python berikut.
In [9]: R2 = Reporter.objects.create(first_name='Harry')
In [10]: R2.save()
Sekarang coba tambahkan R2 ke objek Artikel A1.
In [13]: A1.reporter.add(R2)
Itu tidak bekerja dan Anda akan mendapatkan sebuah AttributeError yang mengatakan objek 'Reporter' tidak memiliki atribut 'tambah'.
Seperti yang Anda lihat objek Artikel tidak dapat dikaitkan dengan lebih dari satu objek Reporter.
Bagaimana dengan R1? Bisakah kita melampirkan lebih dari satu artikel objek ke dalamnya?
In [14]: A2 = Article.objects.create(title='Python News', reporter=R1)
In [15]: R1.article_set.all()
Out[15]: [<Article: Python News>, <Article: TDD In Django>]
Contoh praktis ini menunjukkan kepada kita bahwa Django ForeignKeydigunakan untuk mendefinisikan banyak-ke-satu hubungan.
OneToOneField digunakan untuk membuat hubungan satu-ke-satu.
Kita dapat menggunakan reporter = models.OneToOneField(Reporter)dalam file models.py di atas tetapi itu tidak akan berguna dalam contoh kita sebagai penulis tidak akan dapat memposting lebih dari satu artikel.
Setiap kali Anda ingin memposting artikel baru, Anda harus membuat objek Reporter baru. Ini menghabiskan waktu, bukan?
Saya sangat merekomendasikan untuk mencoba contohnya dengan OneToOneFielddan sadari perbedaannya. Saya cukup yakin bahwa setelah contoh ini Anda akan sepenuhnya mengetahui perbedaan antara Django OneToOneFielddan Django ForeignKey.
OneToOneField (satu-ke-satu) menyadari, dalam orientasi objek, gagasan komposisi, sementara ForeignKey (satu-ke-banyak) berkaitan dengan persetujuan.
Patientdan Organ. Patientdapat memiliki banyak Organs, tetapi Organkaleng hanya milik satu Patient. Ketika Patientdihapus, semua Organjuga dihapus. Mereka tidak bisa eksis tanpa a Patient.
Juga OneToOneFieldberguna untuk digunakan sebagai kunci utama untuk menghindari duplikasi kunci. Seseorang mungkin tidak memiliki autofield implisit / eksplisit
models.AutoField(primary_key=True)
tetapi gunakan OneToOneFieldsebagai kunci utama sebagai gantinya (bayangkan UserProfilemodel misalnya):
user = models.OneToOneField(
User, null=False, primary_key=True, verbose_name='Member profile')
Ketika Anda mengakses OneToOneField Anda mendapatkan nilai dari bidang yang Anda tanyakan. Dalam contoh ini, bidang 'judul' model buku adalah OneToOneField:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
Saat Anda mengakses ForeignKey, Anda mendapatkan objek model terkait, yang kemudian dapat Anda buat sebelumnya. Dalam contoh ini, bidang 'penerbit' model buku yang sama adalah ForeignKey (berkorelasi dengan definisi model kelas Penerbit):
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
Dengan bidang ForeignKey, kueri juga berfungsi sebaliknya, tetapi keduanya sedikit berbeda karena sifat hubungan yang tidak simetris.
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
Di belakang layar, book_set hanyalah QuerySet dan dapat difilter dan diiris seperti QuerySet lainnya. Nama atribut book_set dihasilkan dengan menambahkan nama model huruf kecil ke _set.
OneToOneField: jika tabel kedua terkait dengan
table2_col1 = models.OneToOneField(table1,on_delete=models.CASCADE, related_name='table1_id')
table2 hanya akan berisi satu record yang sesuai dengan nilai pk table1, yaitu table2_col1 akan memiliki nilai unik sama dengan pk tabel
table2_col1 == models.ForeignKey(table1, on_delete=models.CASCADE, related_name='table1_id')
table2 dapat berisi lebih dari satu record yang sesuai dengan nilai pk table1.