2010-09-26 51 views
33

Tôi muốn so sánh ngày tháng với ngày hiện tại ở Django, tốt nhất là trong mẫu, nhưng cũng có thể thực hiện trước khi hiển thị mẫu. Nếu ngày đã trôi qua, tôi muốn nói "Trong quá khứ" trong khi đó là trong tương lai, tôi muốn đưa ra ngày tháng.Cách so sánh ngày tháng trong Django

Tôi đã hy vọng người ta có thể làm điều gì đó như thế này:

{% if listing.date <= now %} 
    In the past 
{% else %} 
    {{ listing.date|date:"d M Y" }} 
{% endif %} 

Với nay là ngày hôm nay, nhưng điều này không hoạt động. Tôi không thể tìm thấy bất cứ điều gì về điều này trong các tài liệu Django. Bất cứ ai có thể đưa ra một số lời khuyên?

Trả lời

72

So sánh ngày trong chế độ xem và chuyển một số thông tin như in_the_past (boolean) sang extra_context.

Hoặc thêm nó vào mô hình làm tài sản.

from datetime import date 

@property 
def is_past_due(self): 
    return date.today() > self.date 

Sau đó, trong giao diện:

{% if listing.is_past_due %} 
    In the past 
{% else %} 
    {{ listing.date|date:"d M Y" }} 
{% endif %} 

Về cơ bản mẫu không phải là nơi để so sánh ngày IMO.

+0

Có, tôi đồng ý rằng các mẫu không phải là nơi để so sánh ngày, nhưng trong trường hợp này, nó có vẻ thanh lịch hơn rất nhiều. Trong mọi trường hợp, tôi cuối cùng đã thực hiện một phương thức trong mô hình django của tôi, inPast(), so sánh ngày với ngày hiện tại và trả về True nếu nó nằm trong quá khứ và sai khác. Điều này sau đó được gọi từ mẫu. Giải pháp của bạn hoạt động tốt hoặc tốt hơn, tôi chỉ tò mò muốn biết liệu có cách nào để thực hiện nó trong mẫu không. –

+2

Tôi không nghĩ như vậy :(Cũng từ kiểu mã hóa, và tái cấu trúc POV, tốt hơn nhiều là có thể tái tạo 'is_past_due' làm thuộc tính hơn nữa trong ví dụ: các mẫu khác nếu không bạn phải sao chép cùng một mã mẫu – bx2

+1

Nếu bạn thực sự, thực sự, thực sự thích xáo trộn xung quanh và so sánh ngày trong mẫu, bạn phải chuyển ngày hiện tại thành extra_context và sau đó sử dụng thẻ 'if' chuẩn, nhưng đây không phải là giải pháp thanh lịch .. – bx2

0

Bạn luôn có thể vượt qua datetime.datetime.now (vì các mô hình django sử dụng đối tượng datetime chuẩn của Python).

Sử dụng render_to_response, bạn có thể làm một cái gì đó như thế này (sau khi nhập datetime):

return render_to_response('template.html', {'now': datetime.datetime.now()}) 

Bây giờ bạn có quyền truy cập vào "bây giờ" bên trong của mẫu, bạn có thể so sánh số ngày giống như bạn đã làm trong của bạn ví dụ.

Hơn nữa, nếu bạn sử dụng RequestContext trong chế độ xem của mình - bạn sẽ có thể thêm "now" dưới dạng context_processor nếu bạn cần điều này trong nhiều tệp. Điều này sẽ thêm "bây giờ" vào bất kỳ mẫu nào được hiển thị với một RequestContext.

Tuy nhiên, nó là thực tế hơn mà bạn chỉ đơn giản là chỉ nhận được danh sách các hồ sơ mà là từ trước đến giờ trong queryset gốc của bạn và tránh truy vấn cho dữ liệu vô dụng ở nơi đầu tiên:

listing.objects.filter(date__lt=datetime.datetime.now()) 
+0

Lọc sẽ được khuyến khích trong hầu hết các trường hợp, nhưng trong trường hợp của tôi đây không phải là hiệu ứng mong muốn: Tôi có danh sách các mục có ngày phát hành nhất định và tôi muốn phân biệt giữa các mục đã được phát hành và những mục chưa được phát hành, nhưng cả hai đều có liên quan đến tìm kiếm. Vì một lý do nào đó biến 'bây giờ', như bạn đã đề xuất, không làm việc cho tôi. ssumed vấn đề là lớn hơn so với trong tuyên bố nếu, rõ ràng là không có sẵn trong tất cả các phiên bản của Django. –

+0

Bạn cần có datetime nhập khẩu với mã này: nhập khẩu datetime Nếu bạn sử dụng: từ datetime datetime nhập khẩu Sau đó, phương pháp thích hợp sẽ là, datetime.now() thay vì datetime.datetime.now() Điều này sẽ làm việc trong tất cả các phiên bản của django. Phiên bản bạn đang sử dụng? – monokrome

9

tôi thêm date_now để tôi danh sách các bộ xử lý ngữ cảnh.

Vì vậy, trong các mẫu có một biến gọi là "date_now" mà chỉ là datetime.datetime.now()

Thực hiện một bộ xử lý bối cảnh gọi date_now trong file context_processors.py

import datetime 

def date_now(request): 
    return {'date_now':datetime.datetime.now()} 

Và trong settings.py, sửa đổi CONTEXT_PROCESSORS để bao gồm nó, trong trường hợp của tôi là

app_name.context_processors.date_now 
1

ngoài @ bx2 câu trả lời có lợi, nếu trường của bạn là trường ngày giờ chỉ cần gọi d Hàm ate() cho các mô hình datetimefield:

from datetime import date 

@property 
def is_past_due(self): 
    if date.today() > self.date.date(): 
     return True 
    return False 
0

Tôi đã tìm thấy câu hỏi này và có vấn đề tương tự. Tôi đã tìm cách hiển thị thông tin nếu nó chỉ xảy ra trong quá khứ.

Sử dụng thẻ "timesince" của Django trong mẫu tôi có thể giải quyết được sự cố của mình. Tôi không nói nó hiệu quả, nhưng nó hiệu quả với tôi.

Trong Template:

{% if model_name.date_time|timesince >= "1 min" %} 
    <p>In the past</p> 
{% else %} 
    <p>{{ model_name.date_time }}</p> 
{% endif %} 
+0

Đó thậm chí không được đề xuất như một giải pháp nhanh chóng, vì bạn đang so sánh các chuỗi. Sau một ngày bạn đang so sánh '" 1 ngày "> =" 1 phút "' là 'Sai' trong khi bạn mong đợi' True' – blacklwhite

7

Tính đến Django 1,8 sau cấu trúc hơi khó chịu không được công việc:

{% now "Y-m-d" as todays_date %} 
{% if todays_date < someday|date:"Y-m-d" %} 
    <h1>It's not too late!</h1> 
{% endif %} 

hackish, nhưng nó tránh được sự cần thiết cho một thẻ tùy chỉnh hoặc xử lý ngữ cảnh.