Лучший и самый эффективный способ узнать что-то новое - это увидеть и изучить практические примеры из реального мира. Предположим на мгновение, что вы хотите создать блог в Django, где журналисты могут писать и публиковать новостные статьи. Владелец интернет-газеты хочет разрешить каждому из своих репортеров публиковать столько статей, сколько они хотят, но не хочет, чтобы разные репортеры работали над одной и той же статьей. Это означает, что когда читатели пойдут и прочитают статью, они увидят в ней только одного автора.
Например: статья Джона, статья Гарри, статья Рика. Вы не можете иметь статью Гарри и Рика, потому что босс не хочет, чтобы два или более авторов работали над одной и той же статьей.
Как мы можем решить эту «проблему» с помощью django? Ключом к решению этой проблемы является django ForeignKey
.
Ниже приведен полный код, который можно использовать для реализации идеи нашего босса.
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
Запустите python manage.py syncdb
, чтобы выполнить SQL-код и построить таблицы для вашего приложения в вашей базе данных. Затем используйте python manage.py shell
, чтобы открыть оболочку Python.
Создание объекта Reporter R1.
In [49]: from thepub.models import Reporter, Article
In [50]: R1 = Reporter(first_name='Rick')
In [51]: R1.save()
Создание объекта Article A1.
In [5]: A1 = Article.objects.create(title='TDD In Django', reporter=R1)
In [6]: A1.save()
Затем используйте следующий фрагмент кода, чтобы получить имя репортера.
In [8]: A1.reporter.first_name
Out[8]: 'Rick'
Теперь создайте объект Reporter R2, выполнив следующий код Python.
In [9]: R2 = Reporter.objects.create(first_name='Harry')
In [10]: R2.save()
Теперь попробуйте добавить R2 к объекту Article A1.
In [13]: A1.reporter.add(R2)
Это не работает, и вы получите AttributeError, в которой говорится, что у объекта 'Reporter' нет атрибута 'add'.
Как видите, объект Article не может быть связан более чем с одним объектом Reporter.
А как насчет R1? Можем ли мы прикрепить к нему более одного объекта Article?
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>]
Этот практический пример показывает нам, что django ForeignKey
используется для определения отношений многие-к-одному.
OneToOneField
используется для создания отношений один-к-одному.
Мы можем использовать reporter = models.OneToOneField(Reporter)
в приведенном выше файле models.py, но в нашем примере он не будет полезен, так как автор не сможет опубликовать более одной статьи.
Каждый раз, когда вы хотите опубликовать новую статью, вам нужно будет создать новый объект Reporter. Это отнимает много времени, не так ли?
Я настоятельно рекомендую попробовать пример с OneToOneField
и понять разницу. Я почти уверен, что после этого примера вы полностью узнаете разницу между django OneToOneField
и django ForeignKey
.