Развертывание Django проекта на виртуальном хостинге

Недавно перенес оба-два свои блога на WordPress с Петерхоста на Locum. Пока полет нормальный — Locum дешевле, удобней и стабильнее. Также я рекомендовал этот хостинг заказчику для размещения небольшого Django сайта, который я сейчас разрабатываю. О том, как развернуть Django 1.4 проект на виртуальном хостинге Locum.ru, и пойдет речь в этом посте.

Итак, в панели управления создаем новый проект, например, mysite.

Заходим на сервер по SSH и скачиваем последний virtualenv:


wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py

Создаем виртуальное Python окружение:


python virtualenv.py ~/env/mysite

Флаг --no-site-packages указывать не нужно — теперь это поведение по умолчанию.

Активируем окружение:


source ~/env/mysite/bin/activate

На локальной машине создаем и редактируем файл зависимостей проекта:


pip freeze > req.txt

Заливаем файл на сервер и устанавливаем все необходимые пакеты:


pip install -r req.txt

С подготовкой окружения закончили, переходим непосредственно к работе с проектом. Все проекты находятся в директории ~/projects, в том числе и наш mysite. Locum создает дефолтный проект автоматом, он не нужен — чистим директории apps, media и static. Заливаем проект и дамп базы. Удаляем wsgi.py файл, использовавшийся на локальной машине, правим файл setting.py. Правим django.wsgi файл, созданный хостингом:


#!/usr/bin/python
# -*- coding: utf-8 -*-
activate_this = '/home/hosting_login/env/mysite/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))
import os
import sys

sys.path.insert(0, '/home/hosting_login/env/mysite/lib/python2.6/site-packages')

sys.path.insert(0, '/home/hosting_login/projects/mysite/apps')

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Собираем статику:


python manage.py collectstatic

Перезапускаем приложение кнопкой в панели хостинга или изменением времени редактирования файла django.wsgi


touch django.wsgi

Не заработал sorl-thumbnail в Ubuntu 12.04

Для ресайза изображений в Django-проектах я пользуюсь батарейкой sorl-thumbnail. Одно из достоинств это приложения — возможность выбора движка для работы с изображениями (по умолчанию PIL). Так вот, после очередного апгрейда Ubuntu, хумбнейлы молча перестали генерироваться.

Даю sorl-thumbnail голос — в settings.py проекта:


THUMBNAIL_DEBUG = True

Вижу причину отказа: IOError: «decoder zip not available». Суть ошибки в том, что в последних версиях Ubuntu (кажется, 11.04) сменилось расположение библиотек libfreetype.so, libjpeg.so и libz.so. А в PIL последней версии эти изменения не учтены. Значит необходимо либо прописать новые пути в setup.py PIL, как описано здесь. Либо поставить симлинки старых путей в системе, как описано здесь. Я выбрал второй вариант, так как ставлю PIL в свое окружение virtualenv для каждого проекта.

Не помешает также установить и все зависимости PIL:


sudo apt-get build-dep python-imaging

STATIC_URL в inclusion template tags

Во включающих шаблонных тегах недоступна переменная STATIC_URL. Получить к ней доступ в шаблоне можно так:


{% load static %}
<img src="{% get_static_prefix %}images/star.png"/>

Либо то же, но чуть короче:


{% load static %}
<img src="{% static "images/star.png" %}"/>

Либо вручную передать из функции тега, импортировав модуль settings.

Время в Django 1.4 и feedparser

При разработке очередного сайта на Django, понадобилось парсить RSS ленту одного из ресурсов. Для парсинга RSS лент отлично подходит пакет feedparser. Некоторые трудности вызвало у меня сохранение даты публикации RSS записи в формате, который требует Django 1.4, с учетом нововведений касающихся TIME_ZONE.

Вот получившееся рабочее решение:


import time
from datetime import datetime
from django.utils import timezone
...
entry_time = datetime.fromtimestamp(
    time.mktime(entry.published_parsed) - time.timezone,
    timezone.get_current_timezone()
)

Django Grappelli 2.4

Grappelli — популярный скин для админки Django, еще не поддерживает недавно вышедшую версию 1.4. А пока установить пакет с помощью pip из нужной ветки Git можно так:


pip install -e git+https://github.com/sehmaschine/django-grappelli.git@grappelli_2_4#egg=django-grappelli

Django и TEMPLATE_CONTEXT_PROCESSORS

Начиная с Django 1.3, переменная TEMPLATE_CONTEXT_PROCESSORS отсутствует в модуле settings. Чтобы добавить свои контекстные процессоры к существующим по-умолчанию — пишем:


from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
...
TEMPLATE_CONTEXT_PROCESSORS += (
    ...
)

И не забываем ставить хвостовую запятую, если в кортеже только один элемент.

robots.txt и class-based generic views в Django

В свое время мне, как не очень искушенному разработчику на Django, было совсем не очевидно как обеспечить отдачу статичного текстового файла. Примером такого файла может быть robots.txt или файлы верификации, часто требующиеся для подтверждения владения сайтом на разнообразных сервисах. При этом, мне бы хотелось, чтобы файл лежал на диске в директории с шаблонами и механизм его отдачи не требовал большого количества кода. Решение было найдено на просторах сети и заключалось в использовании обобщенных представлений (Generic Views) Django. Абстрагируя общеупотребительные идиомы и шаблоны проектирования, обобщенные представления позволяют быстро создавать типичные представления данных с минимумом кода.

Конкретно в данном случае нам может помочь direct_to_template. Для этого в urls.py в соответствующие места добавляем:

...
from django.views.generic.simple import direct_to_template
...
url(
    r'^robots\.txt$',
    render,
    {'template': 'robots.txt','mimetype': 'text/plain'}
),
...

Но с версии 1.3 разработчики Django решили перейти от обобщенных представлений на основе функций (function-based generic views) к обобщенным представлениям на основе классов (class-based generic views). Так что теперь вместо direct_to_template следует использовать TemplateView.as_view(). Но тут возникает небольшая проблема — обобщенные представления на основе классов не поддерживают параметр mimetype. Разработчики сами предлагают решение — отнаследоваться от TemplateView и переопределить метод render_to_response:

...
from django.views.generic.base import TemplateView

class PlainTextTemplateView(TemplateView):
    def render_to_response(self, context, **kwargs):
        return super(PlainTextTemplateView, self).render_to_response(
            context,
            content_type='text/plain',
            **kwargs
        )
...
url(
    r'^robots\.txt$',
    PlainTextTemplateView.as_view(template_name='robots.txt')
),
...

Английский интерфейс в Netbeans 7.1 под Ubuntu

Отличная IDE NetBeans имеет неприятную особенность: интерфейс среды выбирается исходя из системной локали независимо от выбора языка дистрибутива. При этом возможности сменить интерфейс в настройках IDE нет.

Задать локаль можно в конфигурационном файле. В общем случае это path_to_netbeans_folder/etc/netbeans.conf. В моем случае для Ubuntu это /usr/local/netbeans-7.1/etc/netbeans.conf.
В этом файле есть параметр netbeans_default_options в конец его надо добавить конфигураторы -J-Duser.language=en -J-Duser.region=US.

До редактирования:
netbeans_default_options="-J-client -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.zip.disableMemoryMapping=true"

После редактирования:
netbeans_default_options="-J-client -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.zip.disableMemoryMapping=true -J-Duser.language=en -J-Duser.region=US"

Тонкости создания анимации в jQuery

На днях коллега попросил помочь разобраться с небольшой проблемой, с которой он столкнулся при разработке анимационного эффекта на jQuery. Честно говоря, я и сам с ней неоднократно сталкивался, но мне всегда удавалось уклониться от ее решения, используя иные средства.

А суть вот в чем: если навешивать на некое событие анимационные эффекты типа slideDown/slideUp или fadeIn/fadeOut, то отработки анимации последовательно выстраиваются в очередь и выполняются пока очередь не закончится. При этом, если событие происходит с большой частотой, так что анимация не успевает отработать, можно получить нежелательные артефакты в виде долгого дерганья и мигания для slide* и fade* функций соответственно.
Пример 1: http://jsfiddle.net/hrF9k/. Попробуйте быстро поводить мышью над серым квадратом.

Чтобы прервать исполнение очереди вызовов анимации, можно использовать функцию stop(). Но тут возникает неприятный эффект, про который я так и не понял баг это или фича. Значение CSS свойств в момент вызова stop() запоминаются и в последствии используются как максимальные.
Пример 2: http://jsfiddle.net/zGc4w/.

Раньше это ставило меня в тупик, и мне приходилось искать обходные пути реализации задачи. А секрет оказался прост: функция stop() принимает два логических параметра, отвечающих за очистку очереди и переход к предельному значению анимации соответственно.
Пример 3: http://jsfiddle.net/SRAsT/3/

Обновление PyCharm и значки запуска в Ubuntu Unity

В PyCharm на данный момент не реализовано автоматическое обновление. Обновится IDE предлагает, просто скачав очередную версию с сайта разработчиков.
Если при обновлении PyCharm захотелось распаковать дистрибутив в директорию не соответствующую текущей директории установки, то обновить значок запуска Unity можно, отредактировав файл ~/.local/share/applications/jetbrains-pycharm.desktop.
Выходу PyCharm 2.0.2 посвящается.