Django-queryset получает один объект на поле = foo - PullRequest
2 голосов
/ 22 августа 2009

У меня есть базовый FK для пользователя, назовите его владельцем

class Baz(models.Model):

    owner = models.ForeignKeyField(User)


    ....
    ....

Теперь, с набором запросов Baz, есть ли что-то, что я могу связать, что даст мне только один Baz на владельца?

Ответы [ 4 ]

3 голосов
/ 23 августа 2009

Я считаю, что вопрос заключается в том, как запустить эквивалент этого:

SELECT * FROM myapp_baz GROUP BY owner_id;

Который будет возвращать одну строку для каждого уникального идентификатора owner_id.

Похоже, это делает трюк:

qs = Baz.objects.all()
qs.query.group_by = ['owner_id']

# Seems to do the trick
print [item for item in qs]
2 голосов
/ 23 августа 2009

Функция, которую вы действительно ищете, это GROUP BY. Однако Django обычно не поддерживает создание наборов запросов, которые не выводят напрямую экземпляры модели. В этой ситуации у вас есть два подхода:

Baz.objects.values('owner').distinct()

Это даст вам каждого отдельного владельца, но не сам объект Baz.

Baz.objects.filter(pk__in=Baz.objects.values('owner').distinct())

Вышеприведенное выполнит подзапрос (по крайней мере, в MySQL) и должен дать ожидаемые результаты, но не самый эффективный способ его получения.

Наконец, поскольку агрегаты были добавлены, вы можете написать собственный класс агрегатов, который будет работать как своего рода «Distinct» и просто «GROUP BY».

1 голос
/ 23 августа 2009

Это, вероятно, не лучшее решение (хотелось бы не допустить его в память и в наборы запросов), но:

>>> d={}
>>> [d.setdefault(str(a.owner),a) for a in qs ]
>>> d.values()

возвращает список объектов, последний для каждого владельца. У меня есть реальные сомнения относительно масштабируемости этого решения.

0 голосов
/ 22 августа 2009

РЕДАКТИРОВАТЬ : у этого есть более высокий шанс работы:

CheckIn.objects.extra(where=['checkins_checkin.id = (SELECT MAX(checkins_checkin.id) FROM checkins_checkin temp, auth_user WHERE auth_user.id = temp.id AND temp.user_id = checkins_checkin.user_id)',]).count() 
...