2013-05-14 4 views
0

Я получил родитель-дети (1-п) реляционная модель:Как получить единый связанный объект после фильтра

class Parent(models.Model): 
    some_fields = models.IntegerField() 

class Child(models.Model): 
    parent = models.ForeignKey(Parent, relatend_name='children') 
    first = models.BooleanField() 
    second = models.BooleanField() 

Теперь я фильтровать родителей на основе детских полей:

Parent.objects.filter(children__first=True) 

Это порождает следующий SQL:

SELECT app_parent.* 
FROM app_parent 
INNER JOIN app_child ON app_parent.id = app_child.parent_id 
WHERE app_child.first = TRUE 

после того, что я получил все поля Родительские НО Я хочу, чтобы связанные дочерние поля также получили такой SQL:

SELECT app_parent.*, app_child.* 
FROM app_parent 
INNER JOIN app_child ON app_parent.id = app_child.parent_id 
WHERE app_child.first = TRUE 

и получить его через Django ORM. Есть идеи?

UPDATE

Я думаю, что у меня есть хороший обходной

parents = Parent.objects.filter(children__first=True).prefetch_related('children') \ 
.extra(select={'child_id': '"app_child"."id"'}) 
for parent in parents: 
    parent.child = [child for child in parent.children.all() if child == parent.child_id][0] 
+0

Посмотрите на 'for' петли. Существует дочерний атрибут, назначенный aith first child, отфильтрованный из списка предварительно выбранных детей. – ArturM

ответ

1

Вы можете использовать prefetch_related

Parent.objects.filter(children__first=True).prefetch_related('children') 

Или select_related

Child.objects.filter(first=True).select_related('parent') 
+0

Мне просто нужен один ребенок с first = True – ArturM

+0

Если для каждого родителя, являются множественными дочерними, где «first» истинно, тогда вы можете иметь только случайный выбор первой строки в возвращаемом запросе, который вы можете получить с помощью параметра «Parent.objects.filter» (children__first = True) [0] ' –

+0

@ArturM Я добавил информацию 'select_related' для получения одного ребенка назад, но этот другой комментарий поднимает хороший момент ... – Ngenator

0

Вы должны использовать метод fetch_related для этого и делать взгляд вверх наоборот, к сожалению.

В этом случае оно должно быть что-то вроде этого:

first_children = Child.objects.filter(first=True).select_related('parent') 
parents = [c.parent for c in first_children] 
+0

Я использую это решение python atm (btw Я думаю, что он должен быть select_related) – ArturM

+0

Да ... Я запутался с prefetch_related, вы правы :) – Wolph