Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 20, 2010 03:32:30

AlexKiriukha
От:
Зарегистрирован: 2008-02-03
Сообщения: 81
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное (?) поведение ORM

Не пойму как сделать выборку. Пример (упрощённый) моделей:

class Profile(models.Model):
user = models.OneToOneField(User, verbose_name=_('user'), related_name='profile', blank=True, null=True)
phone = models.CharField(_("phone"), max_length=30, blank=True, null=True)


class Unit(models.Model):
owner = models.ForeignKey(Profile, verbose_name=_("owner"), related_name="owned_units", blank=True, null=True)
tenant = models.ForeignKey(Profile, verbose_name=_("tenant"), related_name="tenanted_units", blank=True, null=True)
name = models.CharField(_("unit name"), max_length=255)
Стало нужно выбрать все профили, у которых есть хотя бы один owned_unit или tenanted_unit. Сразу приходит такое решение “влоб”:

Profile.objects.annotate(owned_count=Count('owned_units'), tenanted_count=Count('tenanted_units'))\
.filter(Q(owned_count__gt=0) | Q(tenanted_count__gt=0))
Моя проблема в том, что не могу заставить работать Q, фактически генерируется следующий SQL (postgresql):

SELECT "profiles_profile"."id", "profiles_profile"."user_id", "profiles_profile"."phone",
COUNT("units_unit"."id") AS "owned_count",
COUNT(T4."id") AS "tenanted_count" FROM "profiles_profile"
INNER JOIN "auth_user" ON ("profiles_profile"."user_id" = "auth_user"."id")
LEFT OUTER JOIN "units_unit" ON ("profiles_profile"."id" = "units_unit"."owner_id")
LEFT OUTER JOIN "units_unit" T4 ON ("profiles_profile"."id" = T4."tenant_id")
WHERE ("auth_user"."is_active" = True )
GROUP BY "profiles_profile"."id", "profiles_profile"."user_id", "profiles_profile"."phone"
HAVING (COUNT("units_unit"."id") > 0 AND COUNT(T4."id") > 0 )
Мне тут не нравится избыточные COUNT, но самое главное - почему в HAVING выходит AND? Есть подозрение, что это ошибка. Или всё же моё недопонимание? Пробовал на django-1.2.3 и транковской (django-1.3-pre-alpha), эффект тот же.

Добавлю, что exclude(owned_count=0, tenanted_count=0), которое бы мне тоже подошло, работает так же неверно и генерирует сдедующий HAVING:

HAVING (NOT (COUNT("units_unit"."id") = 0 ) AND NOT (COUNT(T4."id") = 0 ))



Отредактировано (Окт. 20, 2010 03:32:56)

Офлайн

#2 Окт. 27, 2010 17:42:57

AlexKiriukha
От:
Зарегистрирован: 2008-02-03
Сообщения: 81
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное (?) поведение ORM

Я так понимаю или написал пост так, что никто не может понять что имеется ввиду, или никто не сталкивался с такой проблемой (или вообще это не проблема), или вопрос настолько примитивный, что отвечать на него не имеет смысла.

Мне кажется что это ошибка django orm. Но перед тем, как запостить в багтрекер, хотел уточнить у сообщества. Не получил никаких ответов и поэтому нахожусь в растерянности.



Офлайн

#3 Окт. 28, 2010 15:13:21

OZION
От:
Зарегистрирован: 2008-10-15
Сообщения: 89
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное (?) поведение ORM

Попробуй изложить задачу более подробно, а то понять что требуется и вправду сложно.

Офлайн

#4 Ноя. 1, 2010 17:06:40

AlexKiriukha
От:
Зарегистрирован: 2008-02-03
Сообщения: 81
Репутация: +  0  -
Профиль   Отправить e-mail  

Странное (?) поведение ORM

Не выходит подробнее. В общем нужно выбрать все профили, у которых по связям есть один или более owned_units или один или более tenated_units. Мой подход - делать аннотации, но он не работает. Предположительно генерируется неверный sql. Если коллективный разум решит, что таки ошибка в джанго, то пойду делать репорт в багтрекер.



Офлайн

#5 Ноя. 1, 2010 17:20:45

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

Странное (?) поведение ORM

Если правильно понял задачу, то как то так:

Profile.objects.filter(
Q(owned_units__isnull=False) | Q(tenanted_units__isnull=False)
)



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version