gearheart.org.ua

25.06.2011

Аяксовые блоки в джанго

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

Для этого я использовал простую конструкция - inclusion tag, который создает контекст для рендера и view, который вынимал аргументы из запроса и запускал тот же inclusion tag. Получалось, что для одного такого блока приходилось (помимо шаблона) редактировать три файла - тег, обертка-view, объявление в urls.

Мне это надоело и я написал небольшой декоратор, который позволяет автоматизировать весь этот процесс.

03.04.2011

Инвалидация кэша для css спрайтов

При использовании css-спрайтов нужно заставить браузер кэшировать эти изображения на как можно более долгий срок. С другой стороны важно заставить браузер перегружать изображение как только оно изменилось. Это особенно заметно когда все иконки сайта склеены в одно изображение - при использовании устаревшего спрайта весь сайт выглядит криво.

Для решения этой задачи я написал небольшой велосипед, который добавляет к ссылкам на изображения их хеш:

background-image: url(images/icons.png?a3844c660);

03.04.2011

Создание css спрайтов

Написал небольшую библиотеку для создания css-спрайтов. Склеивает изображения из заданной папки в одно и создает соответсвующий css.

11.10.2010

Тестирование авторизации в Django

Чтобы проверить авторизован ли пользователь в тестах, можно использовать такой код:

from django.contrib.auth import get_user

class MyTestCase(TestCase):
    def test_login(self):
        self.assertFalse(get_user(self.client).is_authenticated())
        self.client.login(username='fred', password='secret')
        self.assertTrue(get_user(self.client).is_authenticated())
11.10.2010

Поиск символа в Emacs как в Vim

В виме есть команда поиска символа: f. После первого запуска ее можо повторять точкой с запятой. Мне нравится перемещаться при помощи нее по строке - видишь, что надо перейти к скобке где-то в середине строки - f( и еще пару раз ; чтобы перейти к нужному месту.

В емаксе такой команды нет, пришлось писать самому. Причем получилось даже сделать повторение при помощи ;

23.09.2010

Динамическое создание классов, QuerySetManager и use_for_related_fields

Как оказалось, не все знают, что классы в питоне можно создавать динамически, причем без метаклассов. Приведу пример.

Мы уже научились использовать свой QuerySet для построения цепочек запросов:

Article.objects.old().public()

Теперь надо заставить это работать для связанных объектов:

user.articles.old().public()

Это делается при помощи use_for_related_fields, но нужен небольшой трюк.

23.09.2010

OR и AND без django.db.models.Q

Только сейчас узнал, что для QuerySet определены методы __or__ и __and__. Это значит, что для объединения или пересечания условий выборки можно делать, например:

User.objects.filter(...) | User.objects.filter(...)
User.objects.filter(...) & User.objects.filter(...)
01.07.2010

Переопределение QuerySet

Как известно, менеджеры моделей в Django можно переопределять. Так можно добавить удобные методы для фильтрации:

Article.objects.published()
Article.objects.old()

Но переопределение менеджера не позволяет использовать свои методы по очереди:

Article.objects.published().old()

В этой заметке я расскажу как реализуется такая функциональность.

12.05.2010

Twitter API, OAuth и декораторы

В текущем проекте появилась задача использовать API твиттера. Для авторизации твиттер использует OAuth, который довольно муторный. Чтобы не возиться с ним постоянно, я вынес всю авторизацию в декоратор, так что работа с API выглядит так:

@twitter_api
def tweet_hello(request, api):
    api.update_status('hello')
    # ...

Декоратор проверят наличие ключа, если надо - производит авторизацию. Пользователь перенаправляется на сайт твиттера, дает согласие, перенаправляется обратно и продолжает работу с того же места. Если ключ уже есть - ничего не происходит, просто запускается view.

Удобно, что не нужно делать отдельной настройки твиттера в профиле пользователя.

Код можно посмотреть в продолжении статьи.

20.03.2010

Ajax валидация форм

Возникла задача отправлять форму аяксом, разумеется с проверкой значений. Очевидный способ решения - делать проверку на сервере и возвращать json с ошибками.

Мне очень не нравилась перспектива писать отдельный view для проверки формы и расставлять ошибки по документу яваскриптом. Тем более, что уже есть готовый шаблон формы с ошибками, надо его использовать.

В этой статье я расскажу, как решил для себя эту задачу.

06.03.2010

Переопределение настроек в settings_local

Для локальных настроек проекта я использую известный трюк с settings_local:

try:
    from settings_local import *
except ImportError:
    pass

Тоесть в файле settings_local.py переопределяются настройки из settings.py. Мне было почему-то непонятно как можно свойства дополнить. Например, добавить строку в INSTALLED_APPS, не копируя весь список.

Но вот вчера утром вдруг наконец-то дошло, что можно импортировать settings в settings_local:

# settings_local.py

from settings import *

INSTALLED_APPS += (
    # ...
)
28.02.2010

Объединение нескольких view в Django

Следуя философии UNIX, каждая view выполняет только одну задачу. Это хорошо, но иногда нужно объединить на одной странице логику нескольких view. Отфильтровать, отсортировать, разбить по страницам. Или, например, добавить комментарий прямо на странице товара.

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

18.02.2010

Бизнес-логика в моделях

В последнем моем проекте было очень много бизнес-логики. Потому пришлось как-то структурировать работу с ней. В этой заметке я расскажу о паре приемов, которые, возможно, не для всех очевидны.

18.02.2010

Абсолютные пути в модели

Все знают про permalink, но используют его только для get_absolute_url. Я же предпочитаю задавать все относящиеся к объекту пути в модели:

class Event(models.Model):
    # ...
    @models.permalink
    def edit_url(self):
        return ('event_edit', (self.pk, ))

Затем в шаблоне:

<a href="{{ event.edit_url }}">Редактировать событие</a>
18.02.2010

Профили пользователей с наследованием в Django

Профиль пользователя обычно хранится в одной модели и, если необходимо разделение пользователей на типы, это делается простым текстовым полем user_type или каким-то подобным.

Немного сложнее организовать такие типы пользователей, для каждого из которых нужно хранить разные данные. Тоесть, нужны разные модели.

В этой статье я расскажу каким способом решил такую задачу.