2013-03-26 8 views
4

У меня есть таблицы, называемые «has_location» и «location». «has_location» имеет user_has и location_id и его собственный id, который дается самим django.django model object filter

«местоположения» имеют больше столбцов.

Теперь я хочу получить все местоположения определенного пользователя. То, что я сделал это .. (user.id известно):

users_locations_id = has_location.objects.filter(user_has__exact=user.id) 
locations = Location.objects.filter(id__in=users_locations_id) 
print len(locations) 

, но я получаю 0 этим print. У меня есть данные в db. но у меня такое ощущение, что __in не принимает идентификаторы модели, не так ли?

благодарит

+0

Можете ли вы показать нам соответствующие части этих трех моделей, пожалуйста? –

+0

@ GarethRees, конечно, но они просто обычные модели. Думаю, дело здесь в том, что я могу использовать '' __in''. – doniyor

ответ

4

Вы используете собственный идентификатор has_location для фильтрации местоположения. Вы должны использовать location_id S для фильтрации местоположения:

user_haslocations = has_location.objects.filter(user_has=user) 
locations = Location.objects.filter(id__in=user_haslocations.values('location_id')) 

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

location = Location.objects.filter(has_location__user_has=user.id) 
1

Что ваши модели выглядеть?

За ваши сомнения __indoes accept отфильтрованные идентификаторы.

Для вашего текущего кода, решение:

locations = Location.objects.filter(id__in=has_location.objects.filter(user=user).values('location_id')) 
# if you just want the length of the locations, evaluate locations.count() 
locations.count() 
# if you want to iterate locations to access items afterwards 
len(locations) 
7

Использование __in для такого рода запроса является общим антишаблоном в Django: это заманчиво из-за своей простоты, но плохо масштабируется в большинстве баз данных. См. Слайды 66ff в this presentation by Christophe Pettus.

У вас есть отношения «многие ко многим» между пользователями и местоположениями, представленными таблицей has_location. Вы, как правило, описывают это Django с использованием ManyToManyField с through столом, что-то вроде этого:

class Location(models.Model): 
    # ... 

class User(models.Model): 
    locations = models.ManyToManyField(Location, through = 'LocationUser') 
    # ... 

class LocationUser(models.Model): 
    location = models.ForeignKey(Location) 
    user = models.ForeignKey(User) 
    class Meta: 
     db_table = 'has_location' 

Затем вы можете получить места для пользователя, как это:

user.locations.all() 

Вы можете запросить местоположение в фильтре операциях:

User.objects.filter(locations__name = 'Barcelona') 

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

+0

ничего себе, очень приятно. У меня плохое знание базы данных, очень полезное руководство, спасибо в тоннах. – doniyor

+0

Определенно стоит узнать о базах данных, если вы пишете приложения Django. (В противном случае в один прекрасный день вы обнаружите, что ваше приложение работает слишком медленно, и вы не знаете, как его исправить.) Хорошим первым шагом является включение ведения журнала запросов в вашей базе данных и мониторинг журнала при проверке вашего сайта Django чтобы увидеть, какие запросы фактически выполняются. –

+0

Да, вы правы. я буду следовать вашему руководству – doniyor