Django: следование обратному направлению отношения один-к-одному

У меня вопрос о том, как Django моделирует отношения один-к-одному.

Предположим, у нас есть 2 модели: A и B:

class B(models.Model):
      bAtt = models.CharField()

class A(models.Model):
      b = models.OneToOneField(B)

В созданной таблице A есть поле «b_id», но в таблице B, созданной Django, нет такого поля, как «a_id».

Итак, учитывая объект A, безусловно, быстро получить соответствующий объект B, просто через столбец «b_id» строки A.

Но как Django получает объект A с учетом объекта B?

Наихудший вариант - просмотреть таблицу A для поиска B.id в столбце «b_id». Если да, то целесообразно ли вручную вводить дополнительное поле «a_id» в модели и таблице B?

Заранее спасибо!


person Paul Hoang    schedule 26.09.2011    source источник


Ответы (3)


Достаточно сохранить идентификатор в одной из таблиц.

В случае 1 (a.b) сгенерированный SQL будет

SELECT * from B where b.id = a.b_id

а в случае 2 SQL будет:

SELECT * from A where a.b_id = b.id

Вы можете видеть, что SQL-запросы, сгенерированные в любом случае, похожи и соответственно зависят от их размеров.

Практически во всех случаях индексации должно хватить, а производительность будет хорошей при использовании всего 1 идентификатора.

person lprsd    schedule 26.09.2011
comment
Спасибо. Это полезно, и это то, что я ищу. Я также только что понял, что даже в случае данного A у нас сразу есть b_id, но затем, чтобы получить весь объект B, ему все равно нужно сканирование, как в обратном случае. - person Paul Hoang; 26.09.2011

Django извлекает поле через JOIN в SQL, эффективно объединяя строки двух таблиц вместе, где b_id совпадает с B.id.

Допустим, у вас есть следующие таблицы:

# Table B
| id | bAtt    |
----------------
|  1 | oh, hi! |
|  2 | hello   |

# Table A
| id | b_id |
-------------
| 3  |  1   |
| 4  |  2   |

Затем соединение на B.id = b_id создаст следующие кортежи:

| B.id | B.bAtt  | A.id |
------------------------
|  1   | oh, hi! |  3   |
|  2   | hello   |  4   |

Django делает это независимо от того, с какой стороны вы входите в отношение, и, таким образом, одинаково эффективен :) Как база данных фактически выполняет соединение, зависит от реализации базы данных, но так или иначе он должен пройти через каждый элемент в каждой таблице и сравните атрибуты соединения.

person haeric    schedule 26.09.2011
comment
Не забывайте, что идентификатор индексирован, поэтому сканирование всегда будет быстрым. - person Daniel Roseman; 26.09.2011

Другие объектно-реляционные преобразователи требуют, чтобы вы определяли отношения с обеих сторон. Разработчики Django считают, что это нарушение принципа DRY (Don't Repeat Yourself), поэтому Django требует, чтобы вы определяли отношения только на одном конце.

Всегда обращайте внимание на документ;)

person Mansuro    schedule 26.09.2011
comment
Эта информация очень полезна, спасибо Мансуро. Он не выбран в качестве ответа, так как напрямую не отвечает на мой вопрос о производительности. - person Paul Hoang; 26.09.2011