К примеру есть две модели Book and Scope.
Каждая Book может иметь много scope. На основании этих оценок методов Book.get_rating() определяет оценку самой Book.
Задача в том чтобы создать поле rating для модели Book, чтобы иметь возможность использовать его в админке для сортировки. Для этого используется аннотация вызывающаяся в методе models.QuerySet.
class BookQuerySet(models.QuerySet):
"""
Queryset for books.
"""
def books_with_rating(self):
"""Queryset with rating of each the book."""
return self.annotation(rating=models.Avg('scope'))
Тогда метод Book.get_rating(), будет следующим
def get_rating(self):
"""Getting rating of book on based scopes."""
return self.__class__.objects.books_with_rating().get(pk=self.pk).rating
get_rating.admin_order_field = 'rating'
get_rating.short_description = _('Rating')
Весь алгоритм работает и нет нарушения DRY, и в админке работает сортиорвка по полю rating для Book.
Проблема возникает когда появляется модель Writter и нужно для него определить среднюю оценку его книг и иметь возможность сортировки в админке. Понятно что вновь нужна аннотация.
Только как её сделать с модели Writter, ведь Book ещё не имеет поля rating для каждой книги автора:
то есть аннотация должа быть где-то такое
class WritterQuerySet(models.QuerySet):
def wrritter_with_avg_rating_books(self):
return self.annotation(avg_rating_by_books=models.Avg('rating'))
только вот в поля rating в Books автора ещё нет так как не вызван метод BookQuerySet.books_with_rating().
Нужно как-то решить эту проблему.
Если кто-то может предложить другое решению буду рад узнать.