Изменение по числам в Django

11.10.2009 - 21:05
Авторы: V@s3K
Использованное ПО: Eclipse 3.4.2, Django 1.0.2

В шаблонизаторе django очень много встроенных тегов, которые неплохо помогают в рутинных ситуациях, таких как вывод списка юзеров из массива, удаление пробелов, вывод списка по алфавиту. Все это и многое другое можно прочитать в документации к django:

http://docs.djangoproject.com/en/dev/ref/templates/builtins/

Обладая мощной системой шаблонов все-таки нельзя учесть все пожелания пользователей, а особенно говорящих на разных языках. Именно для этого разработчики и придумали пользовательские теги, позволяющие самому дописать функционал.

В документации есть такой фильтр как pluralize, позволяющий дописывать к числу заданное слово в нужном падеже. Синтаксис его таков:

You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}

Однако вот беда - для русского языка это совершенно не подходит. В английском числа различаются только "одно что-то" и "много чего-то", с соответствующим добавлением окончания -s или других его производных (-es, -ies). В русском может быть три варианта окончаний "один кабачок", "два-три-четыре кабачка", "пять кабачков". Да еще нужно учитывать, что все зависит от последней цифры числа ("двадцать один кабачок"). Да еще у нас есть такие числа как "одиннадцать", "двенадцать" и "тринадцать", которые не поддаются этому правилу. В общем все намного сложнее, чем в английском. Поэтому нам просто необходимо написать свой custom-фильтр.

Мною был взят код, когда-то давно написанный themylogin'ом у себя в wiki для PHP. В определенных пределах он меня вполне устроил.

Все это было переписано на Python'е и вставлено в качестве custom-tag'а в проект django. О создании и правильном размещении подробнее можно прочитать в документации, я опишу вкратце.

У меня есть application "main", создадим папку main/templatetags/, в которую положим пустой файл __init__.py (чтобы Python признал ее как часть проекта) и файл с названием pluralize.py

Далее пропишем 'mysite.main' (где mysite - название проекта) в INSTALLED_APPS в вашем settings.py, чтобы теперь django признал его.

Далее пишем в pluralize,py (Cтарый вариант. Плохо работает при больших числах)

# -*- coding: utf-8 -*-

# Стандартный импорт библиотеки шаблонов

from django import template

# Это чтобы register.filter работал

register = template.Library()

# Расскажем django о нашем крутом фильтре

@register.filter

def rupluralize(value, arg="дурак,дурака,дураков"):

# Берем модуль от нашего числа

number = abs(int(value))

# Так как фильтр поддерживает лишь один аргумент, разбиваем его по запятым

args = arg.split(",")

# Ну а тут основная магия

if (number % 100 == 1) or (number % 100 > 20) and (number % 10 == 1):

return args[0]

if (number % 100 == 2) or (number % 100 > 20) and (number % 10 == 2):

return args[1]

if (number % 100 == 3) or (number % 100 > 20) and (number % 10 == 3):

return args[1]

if (number % 100 == 4) or (number % 100 > 20) and (number % 10 == 4):

return args[1]

return args[2]

Обновленный вариант

По алгоритму GNU: http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html

# -*- coding: utf-8 -*-

# Стандартный импорт библиотеки шаблонов

from django import template

# Это чтобы register.filter работал

register = template.Library()

# Расскажем django о нашем крутом фильтре

@register.filter

def rupluralize(value, arg="дурак,дурака,дураков"):

args = arg.split(",")

number = abs(int(value))

a = number % 10

b = number % 100

if (a == 1) and (b != 11):

return args[0]

elif (a >= 2) and (a <= 4) and ((b < 10) or (b >= 20)):

return args[1]

else:

return args[2]

Написание фильтра закончено. Прицепим его в шаблоне, написав где-нибудь в начале:

{% load pluralize %}

И потом используем:

  • {{ user.mails }} {{ user.mails|rupluralize:"письмо,письма,писем" }}
  • {{ user.posts }} {{ user.posts|rupluralize:"статья,статьи,статей" }}
  • {{ user.comments }} {{ user.comments|rupluralize:"комментарий,комментария,комментариев" }}

И получаем примерно вот такое:

Ну или вот так можно:

вася — 13.09.2010 - 03:41 [178.94.38.212] Linux
а пример по прикручиваниею этого к админке без переопределения всего и вся?
V@s3K — 13.09.2010 - 10:32 [178.49.15.6] Linux
вася, давно не юзал джанговскую стандартную админку, что даже не подскажу.
torsion — 05.10.2010 - 16:02 [95.131.9.202] Linux
Создаете папочку temapltetags в приложении, в ней создается питоний файл, примеру mylib.py(не забудьте положить в эту же папочку init.py), в нем описываете вышеизложеное и всё.
В нужно шаблоне пишите {% load mylib.py %}
V@s3K — 05.10.2010 - 18:18 [178.49.15.6] Linux
> init.py
__init__.py
И еще в сеттингсах прописать надо, если не прописано еще :(

А вообще это описано в посте :)
Виктор — 07.09.2011 - 16:26 [89.169.179.157] Linux
Шикарное решение, спасибо
refresh

i