2012-05-09 47 views
10

Tôi có một mô hình có chứa datefield. Tôi đang cố gắng để có được bộ truy vấn của mô hình đó có chứa tuần hiện tại (bắt đầu vào thứ hai).Bộ lọc truy vấn Django theo số tuần ISO

Vì vậy, kể từ Django datefield chứa đơn giản datetime.date mô hình tôi giả định lọc bằng cách sử dụng .isocalendar(). Về mặt lý thuyết, đó chính xác là những gì tôi muốn mà không có sự so sánh và tính toán bổ sung nào theo ngày trong tuần hiện tại.

Vì vậy, những gì tôi muốn làm về cơ bản có hiệu lực .filter tuyên bố là để cư xử theo logic này:

if model.date.isocalendar()[2] == datetime.date.today().isocalendar()[2] 
    ... 

Tuy nhiên, làm thế nào để viết nó bên tuyên bố bộ lọc? .filter(model__date__isocalendar=datetime.date.today().isocalendar()) sẽ cho kết quả sai (giống như so với hôm nay không phải tuần này).

Như đào đúng http://docs.python.org/library/datetime.html tôi đã không nhận thấy bất kỳ tùy chọn tuần ngày khác ...

Lưu ý từ tài liệu:

date.isocalendar() Return 3 tuple, (ISO năm , Số tuần ISO, ISO các ngày trong tuần).

Cập nhật:

Mặc dù tôi không thích giải pháp của việc sử dụng các dãy nhưng đó là lựa chọn tốt nhất. Tuy nhiên, trong trường hợp của tôi, tôi đã tạo một biến số đánh dấu sự bắt đầu của tuần và chỉ xem xét giá trị lớn hơn hoặc bằng nhau bởi vì nếu tôi đang tìm kiếm một kết quả phù hợp cho tuần hiện tại. Trong trường hợp cho số lượng trong tuần Nó sẽ yêu cầu cả hai đầu.

today = datetime.date.today() 
monday = today - datetime.timedelta(days=today.weekday()) 

... \ 
.filter(date__gte=monday) 
+0

Tôi không biết nếu sự hỗ trợ orm đó nhưng bạn có thể dự phòng để truy vấn thô nếu nó không https://docs.djangoproject.com/en/dev/topics/db/sql/ – dm03514

+0

Tôi biết tùy chọn này dm03514, nhưng tôi muốn viết bộ lọc của riêng mình sau đó. Đó cũng là một lựa chọn nhưng tôi yêu cầu để biết có lẽ nó có thể đạt được điều này bằng cách sử dụng hành động mặc định trong Django mà không cần mở rộng nó. – JackLeo

+1

btw có mô-đun date python tốt đẹp có thể hữu ích http://pypi.python.org/pypi/python-dateutil – aisbaa

Trả lời

8

Bạn sẽ không thể thực hiện việc này. Hãy nhớ rằng nó không chỉ là một vấn đề của những gì Python hỗ trợ, Django phải giao tiếp bộ lọc với cơ sở dữ liệu, và cơ sở dữ liệu không hỗ trợ tính toán ngày phức tạp như vậy. Tuy nhiên, bạn có thể sử dụng __range, với ngày bắt đầu và ngày kết thúc.

+0

Vâng, tôi cũng sẽ sử dụng * __ range *, có thể sự kiện thêm ModelManager tùy chỉnh và Queryset tùy chỉnh với * tuần (phương thức date_field = (2012, 18)) *. – aisbaa

+0

Tôi biết về tùy chọn phạm vi, nhưng tôi đã tránh nó do số lượng hành động được yêu cầu để có được cả hai đầu của tuần, nhưng tôi đoán rằng có thể là cái ác ít hơn. Cảm ơn không ít hơn. – JackLeo

+1

Vâng, không phải mọi phần của ứng dụng của bạn cần phải đủ điều kiện chơi gôn. Đôi khi bạn phải đi một con đường dài hơn. Luôn làm những gì đơn giản nhất, rõ ràng nhất và tạo ra ít dấu chân nhất (sửa đổi cách bộ lọc xử lý Django sẽ để lại một dấu chân khá lớn). –

1

(Câu trả lời này chỉ nên làm việc cho postgres, nhưng có thể làm việc cho cơ sở dữ liệu khác.)

Một giải pháp nhanh chóng và thanh lịch cho vấn đề này sẽ được xác định hai custom transformers:

from django.db import models 
from django.db.models.lookups import DateTransform 

@models.DateTimeField.register_lookup 
class WeekTransform(DateTransform): 
    lookup_name = 'week' 


@models.DateTimeField.register_lookup 
class ISOYearTransform(DateTransform): 
    lookup_name = 'isoyear' 

Bây giờ bạn có thể truy vấn theo tuần như thế này:

from django.utils.timezone import now 
year, week, _ = now().isocalendar() 

MyModel.objects.filter(created__isoyear=year, created__week=week) 

behinds sau hậu trường, các đối tượng Django DateTransform sử dụng postgres EXTRACT function, mà s upports weekisoyear.

0

ExtractWeek đã được giới thiệu ở Django 1.11 để lọc dựa trên số isoweek.

Đối với Django 1.10 và thấp hơn phiên bản, giải pháp sau đây làm việc cho lọc theo tuần số iso trên cơ sở dữ liệu Postgres:

from django.db.models.functions import Extract 
from django.db import models 
@models.DateTimeField.register_lookup 
class ExtractWeek(Extract): 
    lookup_name = 'week' 

Bây giờ làm truy vấn như sau

queryset.annotate(week=ExtractWeek('date'))\ 
      .filter(week=week_number) 
Các vấn đề liên quan