Подсчитать количество записей по дате в Джанго - PullRequest
48 голосов
/ 17 февраля 2010

У меня есть модель, похожая на следующую:

class Review(models.Model):
    venue = models.ForeignKey(Venue, db_index=True)
    review = models.TextField()  
    datetime_created = models.DateTimeField(default=datetime.now)

Я бы хотел запросить базу данных, чтобы получить общее количество отзывов для места, сгруппированного по дням. Запрос MySQL будет:

SELECT DATE(datetime_created), count(id) 
FROM REVIEW 
WHERE venue_id = 2
GROUP BY DATE(datetime_created);

Каков наилучший способ сделать это в Джанго? Я мог бы просто использовать

Review.objects.filter(venue__pk=2)

и проанализируйте результаты в представлении, но мне это не кажется правильным.

Ответы [ 5 ]

86 голосов
/ 17 февраля 2010

Это должно работать (используя ту же функцию, что и MySQL, которую вы использовали):

Review.objects.filter(venue__pk=2)
    .extra({'date_created' : "date(datetime_created)"})
    .values('date_created')
    .annotate(created_count=Count('id'))
15 голосов
/ 24 декабря 2015

Просто для полноты, поскольку extra () нацелена на устаревание, можно использовать такой подход:

from django.db.models.expressions import DateTime

Review.objects.all().\
    annotate(month=DateTime("timestamp", "month", pytz.timezone("Etc/UTC"))).\
    values("month").\
    annotate(created_count=Count('id')).\
    order_by("-month")

У меня это работало в django 1.8, как в базах данных sqlite, так и в MySql.

11 голосов
/ 17 февраля 2010

Если бы вы хранили поле даты, вы могли бы использовать это:

from django.db.models import Count

Review.objects.filter(venue__pk = 2)
    .values('date').annotate(event_count = Count('id'))

Поскольку вы храните дату и время, это немного сложнее, но это должно послужить хорошей отправной точкой. Проверьте агрегирование документов здесь .

10 голосов
/ 30 января 2017

Теперь, когда Extra() амортизируется, более подходящий ответ будет использовать Усечение , например этот принятый ответ

Теперь ответ на вопрос ОП будет следующим:

from django.db.models.functions import TruncDay

Review.objects.all()
    .annotate(date=TruncDay('datetime_created')
    .values("date")
    .annotate(created_count=Count('id'))
    .order_by("-date")
4 голосов
/ 11 апреля 2016

Также вы можете определить пользовательскую функцию:

from django.db.models.expressions import Func

# create custom sql function
class ExtractDateFunction(Func):
    function = "DATE" # thats the name of function, the way it mapped to sql

# pass this function to annotate
Review.objects.filter(venue__pk=2)
      .annotate(date_created=ExtractDateFunction("datetime_created"))
      .values('date_created')
      .annotate(created_count=Count('id'))

Просто убедитесь, что ваш движок БД поддерживает функцию DATE

...