2016-03-01 2 views
0

ИнтроЧетыре стола присоединиться Джанго

Относительно новый Джанго, любопытно, как сделать 4-полосная присоединиться к моей конкретной потребительной случае с использованием ОРМ.

Джанго Модель

class Foo(models.Model): 
    attr1 = ... 

class Bar(models.Model): 
    foo = models.ForeignKey (Foo) 
    attr2 = ... 

class BarOneToOne(models.Model): 
    bar = models.ForeignKey (Bar) 
    attr3 = ... 

class BarManyToOne(models.Model): 
    bar = models.ForeignKey (Bar) 
    attr4 = ... 

Проблема

Хочет перечень BarManyToOne с ассоциированной BarOneToOne, Bar и Foo данными. Хотите отфильтровать это на основе Foo ids.

Пример

данных:

Foo      Bar 
--------------  ----------------------- 
| id | attr1 |  | id | attr2 | foo_id | 
--------------  ----------------------- 
    1 apple   101 larry  1 
    2 orange   102 bob  2 
    3 pear   103 sue  3 
    4 grape   104 laura  1 
         105 nancy  4 

BarOneToOne   BarManyToOne 
------------------  -------------------- 
| bar_id | attr3 |  | bar_id | attr4 | 
------------------  -------------------- 
    101  dog   101  cinnamon 
    103  mouse   104  thyme 
    104  cat   103  garlic 
          104  sea salt 
          101  chili powder 
          103  paprika 

Желаемый результат:

-------------------------------------- 
| apple | larry | dog | cinnamon | 
-------------------------------------- 
| apple | laura | cat | thyme  | 
-------------------------------------- 
| apple | laura | cat | sea salt | 
-------------------------------------- 
| apple | larry | dog | chili powder | 
-------------------------------------- 

SQL Эквивалент

SELECT f.attr1, b.attr2, bmto.attr3, bmtoa.attr4 
FROM foo f, bar b, bar_one_to_one boto, bar_many_to_one bmto 
WHERE bmto.bar_id = boto.bar_id AND b.id = bmto.bar_id 
AND b.foo_id = f.id AND f.id = ?; 

Разное

До сих пор я видел select_related в документации, которая чувствует себя очень полезным. Также __ подход. Чувствует, что здесь есть куски, но пока еще не удалось собрать все это.

С точки зрения производительности/размера таблицы Foo, Bar и BarOneToOne будут небольшими (до 500 строк каждый, даже, вероятно, менее 100 строк). Таблица BarManyToOne будет больше.

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

ответ

0

Вам нужно будет установить связанные_имя для своих моделей в зависимости от вашей системы координат. Существует множество способов сделать это, но для этой цели я буду использовать таблицу BarManyToOne в качестве основной таблицы.

class Foo(models.Model): 
    attr1 = ... 

class Bar(models.Model): 
    foo = models.ForeignKey (Foo, related_name='foo_bars') 
    attr2 = ... 

class BarOneToOne(models.Model): 
    bar = models.ForeignKey (Bar, related_name='bar_baronetoones') 
    attr3 = ... 

class BarManyToOne(models.Model): 
    bar = models.ForeignKey (Bar, related_name='bar_barmanytoones') 
    attr4 = ... 

С настройки модели, показанной выше, это будет код, который нужно будет ссылаться, чтобы получить эквивалент SQL запросов.

BarManyToOne.objects.all().select_related(
    'bar',        # Joins the three other tables 
    'bar__foo',      # with BarManyToOne serving as 
    'bar__bar_baronetoones'   # the main table 
).filter(        # Your (non join condition) WHERE clauses 
    bar__foo_id=<your value here>  # f.id = ? 
).values(        # The columns you want 
    'bar__foo__attr1',     # f.attr1 
    'bar__attr2',      # b.attr2 
    'bar__bar_baronetoones__attr3', # boto.attr3 
    'attr4'       # bmto.attr4 
) 

Вам нужно будет прочитать на related_name, the making queries section и F() expressions.

+0

Будет ли это завтрашним днем, но выглядит как раз то, что мне нужно. Благодаря! – cpentra1

+0

Хорошо. Дайте мне знать, что произойдет. Благодаря! –

+0

FYI, я отредактировал аргументы filter(). Сначала я этого не заметил, но при втором взгляде дополнительные условия WHERE являются условиями JOIN, которые должны быть автоматически включены при выполнении select_related(). –

Смежные вопросы