Запрос Django: вызов значений () для user__userprofile - PullRequest
1 голос
/ 10 июня 2011

У меня есть следующие модели:

class UserProfile(models.Model):
    user = models.OneToOneField(User) 
    score = models.PositiveIntegerField()

class Game(models.Model):
    name = CharField(max_length=100)

class Achievement(models.Model):
    user = models.ForeignKey('User')
    game = models.ForeignKey(Game)

В settings.py я установил AUTH_PROFILE_MODULE в свой класс UserProfile.

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

Итак, я сделал следующее:

candidates = Achievement.objects.filter(game=game).values('user').annotate(nba=Count('id')).filter(nba__gte=5).order_by('-user__userprofile__score')

Теперь это работает, но проблема в том, что я получаю список значений с идентификатором пользователя и его nba (количество достижений). Но мне нужно распечатать счет в шаблоне, а также получить доступ к другим атрибутам UserProfile ...

Поэтому я попытался изменить ".values ​​('user')" на:

.values('user','user__userprofile__score')

Но это не работает! Я получаю ошибку:

invalid field user__userprofile__score

Обратите внимание, что это работает, если я делаю:

.values('user','user__username')

Что, по-видимому, указывает на то, что значения можно вызывать для атрибутов, но не для Foreignkey?

Я также попробовал другой способ, используя приложение "django-batch-select":

batch = Batch('achievement_set').filter(game=game)
candidates = User.objects.batch_select(achieved=batch).exclude(achieved__is_null=True)

Но я получаю ошибку:

Cannot resolve keyword 'achieved' into field.

Это работает, если я удаляю оператор «исключить», но затем я получаю список ВСЕХ пользователей, включая тех, у кого нет никаких достижений для этой игры (они получают: достигнут == [])

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

Ответы [ 2 ]

0 голосов
/ 10 июня 2011

Я думаю, вам нужно удалить values('user') и добавить в конец query_set only('user', 'user__profile') и select_related('user', 'user__profile')

candidates = [i.user for i in Achievement.objects.\
    select_related('user', 'user__userprofile').\
    annotate(nba=Count('id')).\
    filter(game=game, nba__gte=5).\
    only('user', 'user__userprofile').\
    order_by('-user__userprofile__score')]

Я тестирую на своем проекте это select_related и only, и этоработает

>>> db.connection.queries = []
>>> p = [(i.object, i.object.owner) for i in models.ImageOrVideo.objects.\
      select_related('object', 'object__owner').\
      only('object').all().\
      order_by('-object__owner__id')]
...
>>> len(db.connection.queries)
1
0 голосов
/ 10 июня 2011

Вы можете получить профили пользователей одним дополнительным запросом:

UserProfile.objects.filter(user_id__in=[x['user'] for x in candidates])
...