Это выглядит не так уж плохо. У вас есть три запроса к базе данных за пределами ваших циклов for, так что это не проблема N + 1 запросов. Я не могу сказать, что мог понять, что последовало с первого взгляда.
Вы можете использовать только один запрос, чтобы получить список CourseBooking
объектов или значений, помеченных ceName
и crCalDate
ценности. Вы также можете фильтровать по этим значениям. Затем вы можете выполнить всего один проход по всем этим объектам или значениям, настроив диктовку calendar_dates[date][course]
.
Затем вам нужно будет получить набор курсов, присутствующих в любом из курсов. -dicts и преобразовать его в список для использования в качестве верхних заголовков. Затем проработайте даты, заменив каждый из курсов-диктов списком курсов соответствующим значением элемента таблицы.
Я думаю, что этот код, вероятно, будет более понятным, но если код, который у вас есть, работает, он может нестоит потратить время на его изменение. Тем не менее, он позволил бы вам рассчитывать, проще всего, превратив внутренние диктанты курса в коллекции. Обратите внимание, что счетчики имеют значение по умолчанию 0 для любого ключа, вы никогда не получите KeyError.
table = {}
for obj in course_bookings: # annotated with date_anno and course_anno
date, course = obj.date_anno, obj.course_anno
if date not in table:
table[date] = Counter() # or make table a DefaultDict
table[date][course] += 1
course_headers = set()
for course_dict in table:
course_headers.update( course_dict.keys() )
course_headers = sorted( list( course_headers))
date_column = sorted( table.keys() )
Затем вы бы построили список списков, перебирая date_column
и course_headers
, вытаскиваясчитает в правильном порядке, прежде чем передать их для визуализации. Или, вы можете использовать трюк, который я недавно обнаружил:
class DotDict( dict):
def __getattr__( self, key):
return self[attr] # or with a default None, self.get( attr, None)
, который является во всех отношениях диктом, кроме того, что вы не можете использовать setattr
на нем, потому что getattr
сделан так же, какиндексировать его ... так, чтобы механизм шаблонов Django мог ссылаться на {{dotdict.key}}
, не нуждаясь в причудливых пользовательских тегах шаблонов. Работает одинаково хорошо, наследуя от Counter.