2010-02-17 36 views
39

Tôi có một mô hình tương tự như sau:số Tính của hồ sơ theo ngày trong Django

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

Tôi muốn truy vấn cơ sở dữ liệu để có được tổng số đánh giá cho một địa điểm được nhóm theo ngày. Truy vấn MySQL sẽ là:

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

Cách tốt nhất để thực hiện điều này ở Django là gì? Tôi chỉ có thể sử dụng

Review.objects.filter(venue__pk=2) 

và phân tích kết quả trong chế độ xem, nhưng điều đó dường như không phù hợp với tôi.

+0

Bản sao có thể có của [Django: Nhóm theo ngày (ngày, tháng, năm)] (http://stackoverflow.com/questions/8746014/django-group-by-date-day-month-year) – tback

Trả lời

79

này nên hoạt động (sử dụng cùng chức năng MySQL cụ thể mà bạn sử dụng):

Review.objects.filter(venue__pk=2) 
    .extra({'date_created' : "date(datetime_created)"}) 
    .values('date_created') 
    .annotate(created_count=Count('id')) 
+2

Điều đó giống như câu trả lời của tôi nhưng tốt hơn !! – Zach

+0

Đáng buồn là thiếu .extra() .. Rất mạnh mẽ. Cảm ơn! –

+0

Một cái gì đó tôi không thể có được nó ,,, using .extra() TRƯỚC KHI các .values ​​() có một kết quả khác nhau sau đó sử dụng nó SAU mệnh đề .values ​​()? !! Bất kỳ bậc thầy giải thích nào?! –

11

Nếu bạn được lưu trữ một trường dữ liệu, bạn có thể sử dụng này:

from django.db.models import Count 

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

Bởi vì bạn đang lưu trữ datetime, nó phức tạp hơn một chút, nhưng điều này sẽ cung cấp một điểm khởi đầu tốt. Xem tài liệu tổng hợp here.

12

Chỉ cần cho đầy đủ, kể từ khi thêm() là nhằm cho deprecation, người ta có thể sử dụng phương pháp này:

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") 

Nó làm việc cho tôi trong django 1.8, cả trong cơ sở dữ liệu sqlite và MySql.

+0

Cảm ơn người đàn ông, đây là doanh nghiệp. – Dav3xor

+1

bạn cũng có thể sử dụng utango timezone django thay vì pytz.timezone 'django.utils.timezone.get_default_timezone' –

+0

Điều này dường như đã được di chuyển trong [Extract] (https://docs.djangoproject.com/en/1.10/ref /models/database-functions/#django.db.models.functions.datetime.Extract) trong Django 1.10 –

4

Ngoài ra bạn có thể xác định chức năng tùy chỉnh:

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')) 

Chỉ cần chắc chắn rằng động cơ DB của bạn hỗ trợ hàm DATE

1

Bây giờ Extra() đã được khấu hao một câu trả lời thích hợp hơn sẽ sử dụng Trunc như this accepted answer

Bây giờ câu hỏi của OP sẽ được trả lời như sau

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") 
Các vấn đề liên quan