2012-06-11 8 views
3

Есть ли лучший способ запроса, так что мне не нужно зацикливать и добавлять пользователей в список, потому что, когда длина элементов очень велика, скажем 10000, тогда он должен запрашивать 10000 раз. Есть ли способ избежать этого?Как фильтровать элементы без цикла

user_list = [] 
items = Items.objects.all() 
for item in items: 
     userobjects = Users.objects.filter(item=item.id) 
     user = userobjects[0].user 
     user_list.append(user) 
+0

Вы говорите, что знаете, как это сделать непосредственно в базе данных; и мой опыт в том, что пока вы можете выразить это в SQL, вы можете сделать это с помощью django orm! И в худшем случае, [raw sql] (https://docs.djangoproject.com/en/dev/topics/db/sql/) существует для него; но если вы знаете свой SQL-запрос и чувствуете, что ввод его здесь может помочь получить ответ быстрее. – Stefano

ответ

0

Вы можете использовать соединение MYSQL для объединения таблиц и получения ожидаемого результата без аффилирования.

+0

Да, я знаю, как это сделать, используя sql-запросы. хотел знать, есть ли способ сделать это в django – shanks

+0

Просто проверьте документы ... вы получите https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that- span-relations –

1

Update

Как отметил Sandip Агарвал, если вы хотите только первый, есть не просто SQL AFAIK, для выполнения Я хотел бы сделать это как

user_list = [] 
cur = None 
# If there is customized ordering, 
# you could put the customization after 'item' in the following code 
for user in Users.objects.filter(item__isnull=False).order_by('item').iterator(): 
    if cur != user.item_id: 
     user_list.append(user) 
     cur = user.item_id 

Вы не указали код модели Item и User, так что просто догадайтесь здесь:

User.objects.filter(item__isnull=False) 
# or 
User.objects.filter(item__in=Items.objects.all()) 
+0

Я думаю, что magus хочет «первый объект» из «Пользователи», ссылающийся на/каждый предмет «Элементы». –

+0

@SandipAgarwal Спасибо, что напомнили. Я обновил ответ. – okm

+0

Здесь мы все-таки «перебираем» список «Пользователи», если не «Элементы», который по-прежнему стоит дорого. Можно ли это сделать дешевле? –

0

Try:

user_list = User.objects.filter(users__items__in=Items.objects.all()) 

Однако, так как вы не фильтрует элементы, вы на самом деле просто ищет Users, что есть какие-либо Item, так что вы можете сделать:

user_list = User.objects.filter(users__items__isnull=False) 
+0

В вашем решении также не выбирается «первый объект» из «Пользователи», ссылающийся на/каждый предмет «Элементы». –

0

You можно добиться этого, получив при этом все идентификаторы Item, чтобы отфильтровать User с предложением IN (в списке) с отдельным фильтром для возвращаемых пользователей. Я не могу проверить прямо на данный момент, но что-то вроде следующего должен сделать это для вас:

item_ids = Item.objects.all().values_list('id', flat=True) # Get a list of Item id's values, since you don't need the whole Item object 

user_list = User.objects.filter(items__id__in=item_ids).distinct('id') #Distinct on user id/username, filtered on those users matching an item id 

user_list = list(user_list) # Convert to a list 

Примечание: Вы можете использовать Item.objects.all() непосредственно вместо values_list. Это может привести к большему/медленному запросу, попробуйте профилировать его.

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

user_list = User.objects.filter(items__id__in=item_ids).order_by('id').distinct('id') 

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

Смежные вопросы