Это образец, с которым я часто сталкиваюсь в Джанго. Создать свойства, такие как author_name
, очень просто, и они прекрасно работают, когда вы отображаете одну книгу, но количество запросов увеличивается, если вы хотите использовать это свойство для многих книг на странице.
Во-первых, вы можете использовать select_related
, чтобы предотвратить поиск для каждого человека
for role in self.role_set.all().select_related(depth=1):
person_name = role.person.full_name
if role.name:
person_name += ' (%s)' % (role.name,)
names.append(person_name)
return ', '.join(names)
Однако это не решает проблему поиска ролей для каждой книги.
Если вы отображаете список книг, вы можете просмотреть все роли для своих книг в одном запросе, а затем кэшировать их.
>>> books = Book.objects.filter(**your_kwargs)
>>> roles = Role.objects.filter(book_in=books).select_related(depth=1)
>>> roles_by_book = defaultdict(list)
>>> for role in roles:
... roles_by_book[role.book].append(books)
Затем вы можете получить доступ к ролям книги через словарь roles_by_dict
.
>>> for book in books:
... book_roles = roles_by_book[book]
Вам придется переосмыслить свойство author_name
, чтобы использовать такое кэширование.
Я буду стрелять и по бонусным очкам.
Добавьте метод к роли для отображения полного имени и имени роли.
class Role(models.Model):
...
@property
def name_and_role(self):
out = self.person.full_name
if self.name:
out += ' (%s)' % role.name
return out
author_names
рушится на один лайнер, аналогичный предложению Пауло
@property
def authors_names(self):
return ', '.join([role.name_and_role for role in self.role_set.all() ])