Source code for shoop.core.templatetags.shoop_common
# -*- coding: utf-8 -*-
# This file is part of Shoop.
#
# Copyright (c) 2012-2016, Shoop Ltd. All rights reserved.
#
# This source code is licensed under the AGPLv3 license found in the
# LICENSE file in the root directory of this source tree.
"""
Common helpers for Shoop templates.
.. note::
In addition to these, also the price rendering tags from
`shoop.core.templatetags.prices` module are available.
"""
from __future__ import unicode_literals
from datetime import date
from json import dumps as json_dump
from babel.dates import format_date, format_datetime, format_time
from babel.numbers import format_decimal
from django.conf import settings
from django.utils import translation
from django.utils.safestring import mark_safe
from django.utils.timezone import localtime
from django_jinja import library
from jinja2.runtime import Undefined
from shoop.utils.i18n import (
format_money, format_percent, get_current_babel_locale
)
from shoop.utils.serialization import ExtendedJSONEncoder
@library.global_function
[docs]def get_language_choices():
"""
Get language choices as code and text in two languages.
:return:
Available language codes as tuples (code, name, local_name)
where name is in the currently active language, and local_name
is in the language of the item.
:rtype: Iterable[tuple[str,str,str]]
"""
for (code, name) in settings.LANGUAGES:
lang_info = translation.get_language_info(code)
name_in_current_lang = translation.ugettext(name)
local_name = lang_info["name_local"]
yield (code, name_in_current_lang, local_name)
@library.filter
[docs]def money(amount, digits=None, widen=0):
"""
Format money amount according to current locale settings.
:param amount: Money or Price object to format
:type amount: shoop.utils.money.Money
:param digits: Number of digits to use, by default use locale's default
:type digits: int|None
:param widen:
Number of extra digits to add; for formatting with additional
precision, e.g. ``widen=3`` will use 5 digits instead of 2
:type widen: int
:return: Formatted string representing the given amount
:rtype: str
"""
return format_money(amount, digits, widen)
@library.filter
[docs]def percent(value, ndigits=0):
return format_percent(value, ndigits)
@library.filter
[docs]def number(value):
return format_decimal(value, locale=get_current_babel_locale())
@library.filter
[docs]def datetime(value, kind="datetime", format="medium", tz=True):
"""
Format a datetime for human consumption.
The currently active locale's formatting rules are used. The output
of this function is probably not machine-parseable.
:param value: datetime object to format
:type value: datetime.datetime
:param kind: Format as 'datetime', 'date' or 'time'
:type kind: str
:param format:
Format specifier or one of 'full', 'long', 'medium' or 'short'
:type format: str
:param tz:
Convert to current or given timezone. Accepted values are:
True (default)
convert to currently active timezone (as reported by
:func:`django.utils.timezone.get_current_timezone`)
False (or other false value like empty string)
do no convert to any timezone (use UTC)
Other values (as str)
convert to given timezone (e.g. ``"US/Hawaii"``)
:type tz: bool|str
"""
locale = get_current_babel_locale()
if type(value) is date: # Not using isinstance, since `datetime`s are `date` too.
# We can't do any TZ manipulation for dates, so just use `format_date` always
return format_date(value, format=format, locale=locale)
if tz:
value = localtime(value, (None if tz is True else tz))
if kind == "datetime":
return format_datetime(value, format=format, locale=locale)
elif kind == "date":
return format_date(value, format=format, locale=locale)
elif kind == "time":
return format_time(value, format=format, locale=locale)
else:
raise ValueError("Unknown `datetime` kind: %r" % kind)
@library.filter(name="json")
[docs]def json(value):
if isinstance(value, Undefined):
value = None
return mark_safe(json_dump(value, cls=ExtendedJSONEncoder))