Отображение объекта timedelta в шаблоне django

У меня возникли проблемы с тем, чтобы мой шаблон django отображал объект timedelta последовательно. Я попытался использовать временной фильтр в своем шаблоне, но при этом ничего не отображается. Объект timedelta отображается на странице ошибок следующим образом, если я использую Assert False:

time    datetime.timedelta(0, 38, 132827)

Это отображает разницу во времени как:

0:00:38.132827

Я хотел бы показывать только часы, минуты и секунды для каждого объекта timedelta. Есть ли у кого-нибудь предложения о том, как я могу это сделать?


person bgmaster    schedule 02.05.2013    source источник
comment
Этот аналогичный вопрос для Django может быть полезен: "> stackoverflow.com/questions/33105457/   -  person Anupam    schedule 07.01.2020
comment
Отвечает ли это на ваш вопрос? Отображение и форматирование Django DurationField в шаблоне   -  person kloddant    schedule 14.12.2020
comment
Хотя он запрашивает другой формат вывода (и пришел первым), этот вопрос по сути такой же, как stackoverflow.com/questions/33105457/. Я знаю, что этот пост старый и в нем уже есть ответ, но я ответил на него в более надежном формате, в основном для других, и поэтому, когда я неизбежно снова погуглю это и в результате получу эту страницу, я могу увидеть ответ, который Я хочу.   -  person kloddant    schedule 14.12.2020
comment
Я не уверен, с каких пор, но для тех, кто ищет это, Django имеет встроенный фильтр timesince (и timeuntil), который отображает временную дельту в удобном для человека формате (например, «4 дня, 6 часов»). См. документы здесь: docs.djangoproject.com/en/3.1/ ссылка/шаблоны/встроенные/#timesince   -  person SuzukiBKing    schedule 24.03.2021


Ответы (6)


Я последовал совету Питера и написал собственный фильтр шаблонов.

Вот шаги, которые я предпринял.

Сначала я следовал этому руководству, чтобы создать собственный фильтр шаблонов.

Обязательно прочитайте этот раздел о разметке кода.

Вот мой код фильтра

from django import template

register = template.Library()

@register.filter()
def smooth_timedelta(timedeltaobj):
    """Convert a datetime.timedelta object into Days, Hours, Minutes, Seconds."""
    secs = timedeltaobj.total_seconds()
    timetot = ""
    if secs > 86400: # 60sec * 60min * 24hrs
        days = secs // 86400
        timetot += "{} days".format(int(days))
        secs = secs - days*86400

    if secs > 3600:
        hrs = secs // 3600
        timetot += " {} hours".format(int(hrs))
        secs = secs - hrs*3600

    if secs > 60:
        mins = secs // 60
        timetot += " {} minutes".format(int(mins))
        secs = secs - mins*60

    if secs > 0:
        timetot += " {} seconds".format(int(secs))
    return timetot

Затем в моем шаблоне я сделал

{% load smooth_timedelta %}

{% timedeltaobject|smooth_timedelta %}

Пример вывода

введите описание изображения здесь

person chidimo    schedule 25.10.2017

Вы можете попробовать удалить микросекунды из объекта timedelta, прежде чем отправлять его в шаблон:

time = time - datetime.timedelta(microseconds=time.microseconds)
person lonemc    schedule 05.05.2015

Я не думаю, что есть что-то встроенное, и временные дельты не отображают напрямую свои значения часов и минут. но этот пакет включает тег пользовательского фильтра timedelta, который может помочь: http://pydoc.net/django-timedeltafield/0.7.10/

person Peter DeGlopper    schedule 02.05.2013

Насколько я знаю, для этого вам нужно написать собственный тег шаблона. Ниже приведен код, который я придумал на основе кода ядра Django timesince/timeuntil, который должен выводить то, что вам нужно:

@register.simple_tag
def duration( duration ):
"""
Usage: {% duration timedelta %}
Returns seconds duration as weeks, days, hours, minutes, seconds
Based on core timesince/timeuntil
"""

    def seconds_in_units(seconds):
    """
    Returns a tuple containing the most appropriate unit for the
    number of seconds supplied and the value in that units form.

    >>> seconds_in_units(7700)
    (2, 'hour')
    """

        unit_totals = OrderedDict()

        unit_limits = [
                       ("week", 7 * 24 * 3600),
                       ("day", 24 * 3600),
                       ("hour", 3600),
                       ("minute", 60),
                       ("second", 1)
                        ]

        for unit_name, limit in unit_limits:
            if seconds >= limit:
                amount = int(float(seconds) / limit)
                if amount != 1:
                    unit_name += 's' # dodgy pluralisation
                unit_totals[unit_name] = amount
                seconds = seconds - ( amount * limit )

        return unit_totals;


if duration:
    if isinstance( duration, datetime.timedelta ):
        if duration.total_seconds > 0:
            unit_totals = seconds_in_units( duration.total_seconds() )
            return ', '.join([str(v)+" "+str(k) for (k,v) in unit_totals.iteritems()])

return 'None'
person mfitzp    schedule 02.05.2013

Совет написать свой собственный тег шаблона — это 100% правильный путь. Вы будете иметь полный контроль и сможете форматировать его так, как вам нравится. НО - если вы ленивы и хотите быстро найти решение, используя встроенные средства django, вы можете использовать технику взлома, используя встроенный timesince.

По сути, вычтите свою временную дельту из текущего времени и поместите ее в свой шаблон. Например

import datetime
import django.template

tdelta = datetime.timedelta(hours=5, minutes=10)
tm = datetime.datetime.utcnow() - tdelta

django_engine = django.template.engines['django']
template = django_engine.from_string("My delta {{ tm|timesince }}")
print(template.render({'tm': tm})

Выполните приведенный выше код в ./manage.py shell, и результат будет таким:

My delta 5 hours, 10 minutes
person user590028    schedule 25.09.2020

person    schedule
comment
Ответы только на код не очень полезны сами по себе. Было бы полезно, если бы вы могли добавить некоторые подробности, объясняющие, как и почему он отвечает на вопрос. - person SiHa; 29.09.2016