LXF107:Django
Yaleks (обсуждение | вклад) (Новая: {{Цикл/Django}} == В гостях хорошо, а дома лучше == : ''ЧАСТЬ 3 В мире существуют языки, отличные от английского,...) |
Версия 16:08, 21 июня 2009
|
|
|
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Содержание |
В гостях хорошо, а дома лучше
- ЧАСТЬ 3 В мире существуют языки, отличные от английского, и компьютеры попроще IBM Roadrunner. Никита Шультайс покажет, как Django справляется и с тем, и с другим.
До сих пор мы созерцали «админку» на английском языке, однако ее русификация – тоже не проблема. Для этого нуж- но всего лишь добавить в кортеж MIDDLEWARE_CLASSES в файле settings.py следующую строку:
'django.middleware.locale.LocaleMiddleware',
Она вызывает специальный обработчик, который отыскивает нужный перевод. Чтобы определить, какой язык требуется, Django делает следующее:
- Ищет в текущей сессии пользователя значение ключа django_language.
- Если поиск завершился провалом, Django изучает HTTP-заголовок Accept-Language, генерируемый вашим браузером в соответствии с локальными настройками.
- Наконец, если ничего не было найдено, используется значение переменной LANGUAGE_CODE, установленное в файле settings.py.
Если основной аудиторией вашего сайта будут русскоязычные пользователи, имеет смысл присвоить переменной LANGUAGE_CODE в файле settings.py значение ru.
Основным понятием, которым оперирует Django при интернационализации, являются строки перевода – помеченный особым образом текст в ваших исходных кодах или шаблонах. Собственно процесс перевода реализуется библиотекой gettext, которая входит в состав Python. Чтобы ваше приложение стало доступным на нескольких языках, нужно пройти несколько этапов:
- Определить строки перевода в исходных текстах и шаблонах.
- Запустить утилиту make-messages.py, которая найдет все строки перевода и создаст из них языковой файл.
- Перевести полученный языковой файл.
- Запустить утилиту mcompile-messages.py, которая скомпилирует языковой файл в формат, пригодный для его дальнейшего использования системой.
При этом предполагается, что строки перевода используют английский язык.
Что переводить?
Для начала давайте разберемся, как помечаются строки перевода в исходных текстах приложения. Откройте файл news/views.py. В первую очередь, нужно импортировать функцию ugettext() (она, в отличии от gettext(), отлично справляется с Unicode):
from django.utils.translation import ugettext as _
Как можно заметить, для импортированной функции мы создали псевдоним: _ (подчеркивание). Это было сделано для повышения удобочитаемости кода, содержащего большое число строк перевода.
Затем, давайте передадим функции _() текст, который мы собираемся перевести, и присвоим результат переменной application_name:
application_name = _("news")
Поместим эту строку в представление last_news, а переменную application_name передадим в шаблон:
context = RequestContext(request, { "last_news":news, "application_name":application_name })
Теперь откройте шаблон news/templates/news/lats_news.html и добавьте имя нашего приложения в строку 4:
1-3 ... 4 <h2>{{ application_name }}</h2> 5-...
В шаблон news/templates/news/news_detail.html нужно импортировать тэги интернационализации. Для этого в строке 2 напишите:
{% load i18n %}
после чего в шаблоне будет доступен тэг {% trans %} (и не только), с помощью которого мы будем отмечать строки перевода. Замените текст в строке 5:
5 <h1>{{ news.title }}</h1>
на
<h1>{% trans "News" %}<br/>{{ news.title }}</h1>
Думаю, вы уже догадались, как все это работает. В соответствии с нашим планом, настало время запустить специальную утилиту и создать языковый файл.
Вавилонское смешение
Для начала, откройте терминал, перейдите в директорию приложения news и создайте в ней каталог locale:
cd news mkdir locale
Утилита make-messages.py находится в поддиректории bin установки Django. Вызовите ее со следующими параметрами:
python /путь/до/django/bin/make-messages.py -l ru
Если все пройдет удачно, в директории news/locale будут созданы дополнительные каталоги ru/LC_MESSAGES, а в них – языковый файл django.po, который и нужно переводить. Откройте его в любом текстовом редакторе (для удобства можно пользоваться программой KBabel из KDE). Вы увидите следующее:
#: views.py:23 msgid "news" msgstr "" #: templates/news/news_detail.html:5 msgid "News" msgstr ""
Первая запись в каждом блоке указывает место, где была найдена строка перевода, далее идет текст, который нужно перевести, и наконец, сам перевод (у нас его пока нет). Мы специально создали два варианта слова «news» – с заглавной буквы и с маленькой, чтобы наглядно продемонстрировать, что система воспринимает их как разные слова. Заполните пустые строки русскими «новости» и «Новости». После того, как с переводом языкового файла будет покончено, скомпилируйте его. Для этого воспользуйтесь утилитой compile-messages.py, которая опять же входит в состав Django:
python /путь/до/django/bin/compile-messages.py
В каталоге LC_MESSAGES появляется скомпилированный языковой файл django.mo. Все готово: наше приложение теперь поддерживает два языка.
Смена языка на сайте
Мы уже выяснили, как задать язык для клиентов с отключенными cookie, однако далеко не все пользователи догадаются так поступить, да и у большинства ваших посетителей cookie так или иначе включены. Значит, чтобы сменить язык сайта, нужно только переписать cookie, которые за это отвечают. И опять Django не оставляет нас в беде. Для начала откроем главный файл с URL-картами – urls. py, и после строки
(r'^news/', include('news.urls')),
добавим
(r'^i18n/', include('django.conf.urls.i18n')),
Далее, откроем файл settings.py и добавим следующие строки:
TEMPLATE_CONTEXT_PROCESSORS = ( "django.core.context_processors.auth", "django.core.context_processors.i18n", "django.core.context_processors.request", )
Так мы подключим к нашей системе три контекстных процессора, которые добавляют в шаблоны глобальные переменные для работы с текущим пользователем, переменные языковых настроек и содержимое HTTP-запроса, соответственно. Откройте файл media/templates/index.html и после тэга <body> добавьте:
<form action="/i18n/setlang/" method="post">
<input name="next" type="hidden" value="{{ request.PATH_INFO }}" />
<select name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}"
{% ifequal lang.0 LANGUAGE_CODE %}
selected="selected"
{% endifequal%}>{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
В строке 1 задается форма, данные из которой будут направлены на встроенное в Django приложение django.views.i18n.set_language, расположенное по адресу /i18n/setlang/ и отвечающее за смену языка сайта. Оно принимает POST-запрос, содержащий следующие переменные:
- next – адрес, куда будет перенаправлен пользователь после смены языка. Это, как правило, адрес страницы, на которой мы решили поменять язык. Он содержится в переменной request.PATH_INFO, которую мы передаем в шаблон с помощью контекстного процессора django.core.context_processors.request.
- language – язык, который был выбран.
Список языков доступен в переменной LANGUAGES, но если вы посмотрите на сайт (рис. 2), то увидите огромный перечень, из которого нам нужны только два языка. Дело в том, что если в settings.py не определена какая-либо переменная, то ее значение автоматически берется из файла настроек Django – django/conf/global_settings.py, а там представлен кортеж LANGUAGES, содержащий все языки, поддерживаемые системой: это более 40 наименований (в том числе, языки, в которых символы пишутся справа налево). Чтобы оставить только те из них, которые нам действительно необходимы, добавим в файл settings.py следующий кортеж:
LANGUAGES = ( ('en', gettext_noop('English')), ('ru', gettext_noop('Russian')), )
не забыв написать перед ним:
gettext_noop = lambda s: s
Теперь, если вы загрузите сайт, вам будут доступны только два языка. Вернемся опять к нашей форме: в строке 6 вы найдете новый тэг шаблона ifequal – он сравнивает две переданные переменные, и если они одинаковы, выполняет код в строке 7.
Особенности перевода админки
В отличиe от представлений, где мы вызывали функцию ugettext, в «админке» желательно использовать функцию ленивого (отложенного) перевода ugettext_lazy. Ее главное отличие в том, что перевод осуществляется не сразу, а в момент использования строки, например, при обработке шаблона в «админке» Django. Импортируйте эту функцию в файле news/models.py:
from django.utils.translation import ugettext_lazy as _
Каждое поле модели принимает первым позиционным аргументом свое имя, поэтому строку
title = models.CharField(max_length=70)
можно заменить на
title = models.CharField(_('title'),max_length=70)
В дополнение к имени поля можно передать текст справки. Замените на
description = models.CharField(help_text=_('Not more than 255 symbols.'),max_length=255)
И, наконец, если вам уже надоело слово «News» на главной странице «админки», измените его на более подходящее. Добавьте в класс News подкласс Meta (напомню, что он обеспечивает дополнительные настройки модели), а внутри него объявите переменную, отвечающую за множественное число:
class Meta: verbose_name_plural = _('news')
Добавьте каждому полю имя, текст справки (если требуется) и форму множественного числа. Перейдите в каталог news и проделайте те же действия по созданию, переводу и компиляции языковых файлов, что я описывал ранее. После всех операций у вас должно получиться что-то вроде изображенного на рис. 3 и 4.
Кэширование
Наиболее слабыми звеньями работы сайта являются доступ к базе данных и компилирование шаблонов, поэтому стоит сразу задуматься о кэшировании данных. Django прекрасно справляется этой задачей и позволяет создавать и хранить кэш самыми различными способами и в самых разных местах:
- В оперативной памяти. Такая возможность достигается с помощью программы Memcached, которая служит промежуточным звеном между данными в памяти и Django. Несомненно, этот способ является наибыстрейшим, однако ваш сервер должен обладать достаточным количеством памяти, чтобы хватило и для Django, и для кэша.
- В базе данных. В этом случае о скорости доступа к данным нельзя говорить однозначно, так как тут нужно учитывать настройки самой БД; однако если все сделано с умом, можно ожидать хороших результатов.
- В файловой системе. Самый простой вариант. Его мы и будем использовать.
Откроем файл settigns.py и объявим в нем переменную:
CACHE_BACKEND = 'file:///путь/до/кэша'
Слово file означает, что мы собираемся использовать файловую систему (против memcached и db для оперативной памяти и СУБД, соответственно), далее идут три слэша и путь до директории, в которой вы собираетесь хранить данные.
Django предоставляет высокоуровневые механизмы для генерации кэша и извлечения его из базы данных. Так, самым верхним объектом является кэш всех страниц сайта. Однако если на странице находятся динамические данные, которые индивидуальны для каждого пользователя, например, строка приветствия («Здравствуйте, Имя»), то все посетители будут видеть приветствие для пользователя, который зашел на сайт самым первым. Если же таких элементов нет, это – самый быстрый способ создать кэш сайта. Чтобы включить его, достаточно добавить строку 'django.middleware.cache.CacheMiddleware' в кортеж MIDDLEWARE_CLASSES в файле настро- ек. Она должна стоять самой первой в кортеже. На нашем сайте нет приветствия, однако есть возможность смены языков, и после того как кэш страницы создан для одного языка, он будет отображаться и для другого.
Следующим глобальным объектом для кэширования является представление. И опять, здесь мы сталкиваемся с теми же недостат- ками, что и при кэшировании всех страниц сайта, с единственным отличием: мы сами вправе выбирать, какие страницы будут кэши- роваться, а какие – нет. Вы можете импортировать в ваше представ- ление декоратор cache_page:
from django.views.decorators.cache import cache_page
и применить его к какому-либо представлению, например:
@cache_page(60 * 15) def last_news(request): ...
Декоратор принимает единственный параметр – время жизни кэша в секундах.
Аналогично можно кэшировать и шаблоны. Откройте файл news/templates/news/last_news.html и добавьте после {% extends «index.html» %} строку:
{% load cache %}
далее, перед {% for news in last_news %} добавьте
{% cache 31536000 last_news LANGUAGE_CODE %}
а после {% endfor %}:
{% endcache %}
Сначала мы подключаем дополнительные тэги для кэширования, затем вызываем тэг {% cache %} с тремя параметрами (вообще-то достаточно двух). Первый – время жизни кэша в секундах (у нас это целый год), второй – название, а третий – тоже название, но в нашем случае это переменная, которая вычисляется динамически, а следовательно, для разных языков у нас создается свой кэш. То же самое можно сделать и для приветствия.
Сигналы
Кэширование позволяет сделать сайт очень быстрым, но как быть, если вы определили время жизни кэша в три дня и добавили новость через два? Ведь пока кэш жив, система будет отображать именно его, и нашим посетителям придется ждать целый день. С другой стороны, ставить слишком маленький промежуток тоже нет смысла – тогда от системы кэширования не будет пользы. Предугадать невозможно, да и незачем. Оптимальный вариант – удалять кэш при наступлении какого-либо события (новость добавлена, новость удалена и т.д.). Уведомлением о событии служит сигнал. Создадим внутри директории news файл signals.py следующего содержания:
from django.core.cache import cache
from settings import LANGUAGES
def delete_last_news_cache():
for lang in LANGUAGES:
cache.delete('last_news:'+ lang[0])
Обратите внимание на строку 6, где мы генерируем имя кэша. Здесь учтено, что Django соединяет все, что было передано тэгу {% cache %}, символом двоеточия. Поскольку мы не знаем, для каких языков был создан кэш, то удаляем все возможные варианты – в нашем случае их всего два.
Как же сделать, чтобы этот код выполнялся? Проще простого. Откроем файл news/models.py и добавим в начало следующие строки:
from django.db.models import signals from django.dispatch import dispatcher from news.signals import delete_last_news_cache
а в конец:
dispatcher.connect(delete_last_news_cache,signal=signals.post_save,sender=News) dispatcher.connect(delete_last_news_cache,signal=signals.post_delete,sender=News)
Теперь в системе зарегистрированы два сигнала от передатчика (sender) News. Первый сигнал генерируется после сохранения объекта в базе данных, то есть при его создании или изменении, а второй – после удаления. В обоих случаях выполняется функция delete_last_news_cache, определенная выше. Вообще, для обращения к базе данных в Django существует семь сигналов: pre_init, post_init, pre_save, post_save, pre_delete, post_delete и post_syncdb, названия которых говорят сами за себя.
И сверх этого
Кроме возможности создавать кэш ваших данных, Django поддерживает и другие способы оптимизации. Чтобы сделать ваш сайт еще, быстрее нужно добавить в кортеж MIDDLEWARE_CLASSES в файле settings.py следующие строки:
'django.middleware.http.ConditionalGetMiddleware', 'django.middleware.gzip.GZipMiddleware',
Первая из них включает поддержку условных GET-запросов (использование ETag и Last-Modified в HTTP-заголовках), а вторая отвечает за сжатие содержимого для браузеров, которые поддерживают такую возможность (а это все современные реализации).