Yanıtlar:
OneToOneField(SomeModel)
Ve arasında bazı farklar olduğunu fark etmeye dikkat edin ForeignKey(SomeModel, unique=True)
. Django'nun Kesin Kılavuzunda belirtildiği gibi :
OneToOneField
Bire bir ilişki. Kavramsal olarak, bu bir
ForeignKey
ile benzerdirunique=True
, ancak ilişkinin "ters" tarafı doğrudan tek bir nesneyi döndürür.
OneToOneField
"Ters" ilişkinin aksine, "ters" ilişki a ForeignKey
döndürür QuerySet
.
Örneğin, aşağıdaki iki modelimiz varsa (aşağıdaki tam model kodu):
Car
model kullanır OneToOneField(Engine)
Car2
model kullanır ForeignKey(Engine2, unique=True)
İçinden python manage.py shell
aşağıdakileri yürütün:
OneToOneField
Misal>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car
<Car: Audi>
ForeignKey
ile unique=True
, Örnek>>> 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.car
da işe yarayacak bir kurala sahip olamamasının temel bir nedeni var mı?
ForeignKey
ile unique=True
yerine OneToOneField
? Diğer sorularda, Django'nun OneToOneField
genellikle en iyi hizmetin çıkarlarının olduğunu uyardığını görüyorum . Tersi QuerySet
asla birden fazla öğeye sahip olmayacak, değil mi?
Bir ForeignKey bire çok içindir, bu nedenle bir Car nesnesinin birçok Tekerlekleri olabilir, her bir Tekerlek ait olduğu Arabaya bir YabancıKey'e sahiptir. Bir OneToOneField, bir Car nesnesinin yalnızca bir tanesine sahip olabileceği bir Motor gibi olacaktır.
Yeni şeyler öğrenmenin en iyi ve en etkili yolu, gerçek dünyadaki pratik örnekleri görmek ve çalışmaktır. Django'da gazetecilerin haber makaleleri yazabileceği ve yayınlayabileceği bir blog oluşturmak istediğinizi varsayalım. Çevrimiçi gazetenin sahibi, gazetecilerinin her birinin istedikleri kadar makale yayınlamasına izin vermek istiyor, ancak farklı gazetecilerin aynı makale üzerinde çalışmasını istemiyor. Bu, okuyucular bir makaleye gidip okuduklarında makalede yalnızca bir yazar görecekleri anlamına gelir.
Örneğin: John'dan makale, Harry'den makale, Rick'den makale. Harry ve Rick'in makalesi olamaz, çünkü patron iki veya daha fazla yazarın aynı makale üzerinde çalışmasını istemiyor.
Bu 'problemi' django yardımıyla nasıl çözebiliriz? Bu sorunun çözümünün anahtarı django'dur ForeignKey
.
Patronumuzun fikrini uygulamak için kullanılabilecek tam kod aşağıdadır.
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
Run python manage.py syncdb
sql kodu çalıştırmak ve veritabanınızda uygulamanız için tabloları oluşturma. Sonra python manage.py shell
bir piton kabuğu açmak için kullanın .
Reporter nesnesi R1'i oluşturun.
In [49]: from thepub.models import Reporter, Article
In [50]: R1 = Reporter(first_name='Rick')
In [51]: R1.save()
Makale nesnesi A1'i oluşturun.
In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)
In [6]: A1.save()
Sonra muhabirin adını almak için aşağıdaki kod parçasını kullanın.
In [8]: A1.reporter.first_name
Out[8]: 'Rick'
Şimdi aşağıdaki python kodunu çalıştırarak Reporter nesnesi R2'yi oluşturun.
In [9]: R2 = Reporter.objects.create(first_name='Harry')
In [10]: R2.save()
Şimdi A1 nesne nesnesine R2 eklemeyi deneyin.
In [13]: A1.reporter.add(R2)
Çalışmıyor ve 'Reporter' nesnesinin 'add' özelliği yok diyen bir AttributeError alacaksınız.
Gördüğünüz gibi bir Makale nesnesi birden fazla Reporter nesnesiyle ilişkilendirilemez.
R1 ne olacak? Birden fazla Makale nesnesi ekleyebilir miyiz?
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>]
Bu pratik örnek bize django'nun ForeignKey
bire bir ilişkileri tanımlamak için kullanıldığını göstermektedir.
OneToOneField
bire bir ilişkiler oluşturmak için kullanılır.
reporter = models.OneToOneField(Reporter)
Yukarıdaki models.py dosyasında kullanabiliriz , ancak bir yazarın birden fazla makale yayınlayamayacağı için örneğimizde yararlı olmayacaktır.
Her yeni makale göndermek istediğinizde yeni bir Reporter nesnesi oluşturmanız gerekir. Bu zaman alıcı, değil mi?
Örneği ile denemenizi OneToOneField
ve farkı fark etmenizi şiddetle tavsiye ederim . Bu örnekten sonra django OneToOneField
ve django arasındaki farkı tam olarak bileceğinizden eminim ForeignKey
.
OneToOneField (bire bir), nesne yöneliminde kompozisyon kavramını gerçekleştirirken, ForeignKey (bire-çok) anlaşma ile ilgilidir.
Patient
ve Organ
. Patient
birçok Organ
s olabilir, ancak bir Organ
kutu sadece birine aittir Patient
. Ne zaman Patient
silinir, bütün Organ
ler de silinir. Onlar olmadan var olamazlar Patient
.
Ayrıca OneToOneField
temel tekrarından kaçınmak için birincil anahtar olarak kullanılacak yararlıdır. Birinin üstü kapalı / açık otomatik alanı olmayabilir
models.AutoField(primary_key=True)
ancak OneToOneField
bunun yerine birincil anahtar olarak kullanın ( UserProfile
örneğin modeli hayal edin ):
user = models.OneToOneField(
User, null=False, primary_key=True, verbose_name='Member profile')
Bir OneToOneField öğesine eriştiğinizde, sorguladığınız alanın değerini alırsınız. Bu örnekte bir kitap modelinin 'başlık' alanı bir OneToOneField'dir:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
Bir ForeignKey'e eriştiğinizde, ilgili model nesnesini alırsınız; daha sonra başka sorguları önceden oluşturabilirsiniz. Bu örnekte aynı kitap modelinin 'yayıncı' alanı bir ForeignKey'dir (Yayıncı sınıfı model tanımıyla ilişkili):
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
ForeignKey alanları ile sorgular başka şekilde de çalışır, ancak ilişkinin simetrik olmayan yapısı nedeniyle biraz farklıdırlar.
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
Sahnelerin arkasında, book_set sadece bir QuerySet'tir ve diğer QuerySet gibi filtrelenebilir ve dilimlenebilir. Book_set öznitelik adı, _set öğesine küçük harfli model adı eklenerek oluşturulur.
OneToOneField: İkinci tablo aşağıdakilerle ilgiliyse
table2_col1 = models.OneToOneField(table1,on_delete=models.CASCADE, related_name='table1_id')
table2, table1'in pk değerine karşılık gelen sadece bir kayıt içerecektir, yani table2_col1, tablonun pk değerine eşit benzersiz bir değere sahip olacaktır
table2_col1 == models.ForeignKey(table1, on_delete=models.CASCADE, related_name='table1_id')
table2, table1'in pk değerine karşılık gelen birden fazla kayıt içerebilir.