2010-11-21 5 views
0

У меня есть список объектов:Объединить данные модели со списком объектов

film_hc = [{'count': 2, 'pk': '33'}, 
      {'count': 1, 'pk': '37'}, 
      {'count': 1, 'pk': '49'}] 

Значение «рк» является первичным ключом для записи в модели. Я хотел бы добавить поле имени этой записи в этот список объектов. Чтобы получить одно имя, я могу использовать:

record = Film.objects.get(pk = film_hc[0]['pk']) 
record.name 

В конце концов, я хотел бы иметь что-то вроде этого:

film_hc = [{'count': 2, 'pk': '33', 'name': 'name1'}, 
      {'count': 1, 'pk': '37', 'name': 'name2'}, 
      {'count': 1, 'pk': '49', 'name': 'name3'}] 

Вопрос: Что является наиболее эффективным способом, чтобы прикрепить необходимые данные в этот существующий список?

Я имею в виду, я мог бы использовать функцию почтового индекса:

film_hc_with_names = zip(????, film_hc) 

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

ответ

1

Чтобы избежать попадания в базу данных несколько раз, я рекомендую использовать метод запроса in_bulk. Это принимает список идентификаторов и возвращает словарь идентификатора, сопоставленного с экземпляром модели. Итак, вам нужно сначала запустить список ваших словарей, чтобы извлечь идентификационные значения, затем выполнить запрос, а затем выполнить пробел, чтобы получить имя для каждого экземпляра. Несмотря на то, что он выполняет две дополнительные итерации, он все равно должен быть быстрее, чем выполнение нескольких запросов к БД (хотя, как всегда, вы должны профиль, чтобы убедиться).

id_list = [film['id'] for film in film_hc] 
objects = Film.objects.only('name').in_bulk(id_list) 
for film in film_hc: 
    film['name'] = objects[film['id']].name 
+0

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

+0

@ Конечно, это зависит от вас, но вы не должны просто сосредоточиться на итерации как на главной неэффективности. Попадание в базу данных нескольких отдельных времен намного более неэффективно. Быстрый тест, выполняющий 'ab' для 100 ударов по моему коду против вышеперечисленного aaronsterling показал 0,370 мс для моих против 0,542 мс для него: так мой метод примерно на 50% эффективнее. –

+0

hmm. Ты прав. Протестировано, и это работает намного быстрее. Спасибо за продолжение. –

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