Django список всех авторов по последнему рейтингу - PullRequest
3 голосов
/ 08 августа 2011

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

 class Author(models.Model):
     name = models.CharField(max_length=50)
     email = models.EmailField()

 class Entry(models.Model):
     headline = models.CharField(max_length=255)
     pub_date = models.DateTimeField()
     mod_date = models.DateTimeField()
     authors = models.ForeignKey(Author)
     rating = models.IntegerField()

В конце концов я хотел бы превратить это в словарь Python вроде: {1star: (author1, author2), 2star: (author3, author4, author5) ...}.

Одна мысльвернуть все записи, а затем использовать itertools.groupby для манипулирования большим набором данных.Кто-нибудь может предложить более чистую альтернативу?

Ответы [ 3 ]

2 голосов
/ 08 августа 2011

Другой подход

from collections import defaultdict
from datetime import datetime, timedelta

week_ago = datetime.now() - timedelta(days=7)

author_recent_ratings = dict(Entry.objects.filter(pub_date__gt=week_ago)
                                          .order_by('pub_date')
                                          .select_related()
                                          .values_list('author', 'rating'))

recent_by_rating = defaultdict(list)
for author, rating in author_recent_ratings.iteritems():
    recent_by_rating[rating].append(author)

Это один из способов, которым вы могли бы сделать это.В основном вы упорядочиваете по самым последним записям (в данном случае записи за последнюю неделю), затем упорядочиваете по самым старым, а затем преобразуете список, возвращаемый списком значений, в dict.Что происходит, так как он преобразуется в диктовку, а новые записи забивают более старые, и в итоге вы получаете диктовку, в которой ключами являются авторы, а их значения - значения.

2 голосов
/ 08 августа 2011

Последние трудно сделать в ванильном Django без большой работы (макс, среднее и т. Д. Все можно сделать с помощью аннотаций и агрегаций).

Я делаю это с помощью специального менеджера, например:

class AuthorManager(models.Manager):
  def with_recent_rating(self):
    return super(AuthorManager, self).get_query_set().extra(
        select={
            'recent_rating': '''
                SELECT e.rating
                FROM myapp_entry e
                WHERE e.authors_id = myapp_author.id
                ORDER BY e.pub_date DESC
                LIMIT 1
                ''',
        })

Затем добавьте в модель Author следующее:

class Author():
    ...
    objects = AuthorManager()

Затем, когда вы хотите, чтобы авторы с оценками просто запрашивали:

authors = Author.objects.with_recent_rating().filter(...)

Это практическита же скорость, что и у любой другой выборки, за исключением того, что теперь авторы имеют поле недавних оценок ::1012*

for author in authors:
    print author.recent_rating
1 голос
/ 09 августа 2011

Вы можете сделать это полностью в своем шаблоне.Примерно так должно работать:

**Views.py**
authors = Author.objects.all()

**Template**
{% regroup authors by rating_set.all|last as rating_list %}

{% for rating in rating_list %}
    <b>{{ rating.grouper }}</b><br>
    {% for author in rating.list %}
        {{ author.name }}<br>
    {% endfor %}
{% endfor %}

По сути, этот метод группирует всех ваших авторов по рейтингу, используя тег шаблона regroup.Фильтр last должен давать вам самую последнюю оценку в списке оценок каждого автора.После этого это просто базовое упражнение по перегруппировке, которое разбивает его по рейтингу и отображает всех авторов для каждого рейтинга.

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#regroup

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#last

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...