Django template - Is there a built-in way to get current date as type 'date' instead of type 'str'?

旧时模样 提交于 2019-12-17 21:35:50

问题


I know I can get the current date as a str in a Django template (using the template tag now), like this:

{% now "Y-m-d" as today_str %}
<p>{{ today_str }}</p>

But I cannot use that for comparissons:

{% now "Y-m-d" as today_str %}

{% for elem in object_list %}
    {% if elem.date < today_str %}        {# WRONG: this compares 'date' and 'str' #}
        <p>{{ elem.pk }} before today</p>
        {# do some other rendering #}
    {% endif %}
{% endfor %}

Possible solutions:

  1. I know I can pass a context variable to the template, but it requires code in my view:

    # in my class-based-view in 'views.py'
    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['today'] = timezone.now()
        return ctx
    
  2. Or I can create a custom template tag, but that is even more additional code.

As you can see I have workarounds for my problem, but I would like to know if there is a buit-in way to get the current date (or datetime) in the template?


回答1:


So, all my searching didn't yield a short solution. The answer to the question seems to be: no, there is no buit-in way to get the current date (or datetime) as a variable in the template.

In case others are searching for this topic, I'll try to give a summary of the possible workarounds that I can up with and that were suggested by other users.


  1. I could pass a context variable to the template from my view. In class-based views that could look like this (it is even an example in the docs):

    # file 'my_app/views.py'
    from django.utils import timezone as tz
    from django.views.generic import ListView
    
    class MyView(ListView)
        ...
    
        def get_context_data(self, **kwargs):
            ctx = super().get_context_data(**kwargs)
    
            now = tz.now()
            ctx['now'] = now
            ctx['today'] = tz.localtime(now).date()
    
            return ctx
    
  2. I could create a custom context processor that loads that variable to every template. In class-based views that could look like this:

    # file 'context_processors.py'
    from django.utils import timezone as tz
    
    def now_and_today(request):
        now = tz.now()
        return {
            'now': now,
            'today': tz.localtime(now).date(),
        }
    
    # file 'settings.py'
    ...
    TEMPLATES = [
        {
            ...
            'OPTIONS': {
                'context_processors': [
                    ...
                    'context_processors.today_and_now',
                ],
            },
        },
    ]
    ...
    
  3. I could create a custom template tag, like this:

    # file 'my_app/custom_template_tags/custom_time_tags.py'
    from django.utils import timezone as tz
    from django import template
    register = template.Library()
    
    @register.simple_tag
    def get_now(request):
        return tz.now()
    
    @register.simple_tag
    def get_today(request):
        return tz.localtime(tz.now()).date()
    

    To be used like this:

    {% load 'custom_time_tags' %}
    
    {% get_today as today %}
    {% for per in person_list %}
        {% if per.brith_date > today %}
            <p>{{ per.name }} is from the future!!<p>
        {% endif %}
    {% endfor %}
    
  4. I could also add a property (or even a cached_property) to the model:

    # file 'models.py'
    from django.db import models
    from django.utils import timezone as tz
    from django.utils.functional import cached_property
    
    class Person(models.Model):
        ...
    
        @cached_property
        def is_from_future(self):
            # careful: for long-lived instances do not use 'cached_property' as
            # the time of 'now' might not be right later
            if self.birth_date > tz.localtime(tz.now()).date():
                return True
    
            return False
    
  5. And last but not least, I could just do the processing in the view and add a property to the elements:

    # file 'my_app/views.py'
    from django.utils import timezone as tz
    
    def person_list(request):
        today = tz.localtime(tz.now()).date()
    
        person_list = []
        for p in Person.objects.all():
            p.is_from_future = self.birth_date > today
            person_list.append(p)
    
        return render(request, 'some_template.html', {'person_list': person_list})
    


来源:https://stackoverflow.com/questions/52296306/django-template-is-there-a-built-in-way-to-get-current-date-as-type-date-ins

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!