Анатолий Ларин

Блог о разработке и разработчике

Роботы

Интро

Неделю назад решил установить на блог счетчик-пузомерку – FeedBurner. И я был приятно удивлен, что на мои статьи подписано более двухсот человек!

Спасибо, вам, коллеги!
Спасибо за то, что уделяете внимание моим статьям и иногда активно комментируете. Кстати, о комментриях и фидбэке. До этого, практически, все мои статьи заканчивались решением той или иной задачи. Теперь же я хочу предложить вам, решить задачу самостоятельно. Задача не сложная в реализации, но требует некоторой гибкости мышления.

И так… Read the rest of this entry »

Django 1.2.1 и load_related_m2m

Интро

Думаю, многие из нас занимались оптимизацие загрузки данных из полей ManyToManyField. Задача для оптимизации проста: есть коллекция объектов с некоторым полем (полями) М2М. Необходимо выбрать данные для поля М2М одним запросом, т.е. не выполнять для каждого объекта из коллекции отдельный запрос, по загрузке однотипных данных.

Думаю, многие для этого писали собственные функции, я же пользовался load_related_m2m, найденной когда-то толи на djbook.ru, толи на сайте Ивана Сагалаева.

И вот при обновлении до Django 1.2.1 при вызове функции load_related_m2m, появилась ошибка: ‘DatabaseWrapper’ object is not callable

Исправляем

Очевидно, произошло это из-за смены интефейсов класса django.db.models.sql.Query. Для возобновления работоспособности необходимо изменить буквально пару строк:

Код


# -*- coding: utf-8 -*-
from django.db.models.sql.constants import LOOKUP_SEP
from django.db.models import sql
from django.db import connection                                               

def load_related_m2m(object_list, field):                                      

    select_fields = ['pk']
    related_field = object_list.model._meta.get_field(field)
    related_model = related_field.rel.to
    cache_name = 'all_%s' % field                                              

    for f in related_model._meta.local_fields:
        select_fields.append('%s%s%s' % (field, LOOKUP_SEP, f.column))         

    query = sql.Query(object_list.model)
    query.add_fields(select_fields)
    query.add_filter(('pk__in', [obj.pk for obj in object_list]))

    related_dict = {}
    cursor = connection.cursor()
    cursor.execute(str(query))

    for row in cursor.fetchall():
        if row[2]:
            related_dict.setdefault(row[0], []).append(related_model(*row[1:]))

    for obj in object_list:
        try:
            setattr(obj, cache_name, related_dict[obj.pk])
        except KeyError:
            setattr(obj, cache_name, [])

    return object_list

З.Ы.

А лето выдалось жаркое. Такое чувство, что в тени +40 )

RM

Интро

Случалось ли вам, работая в консоли, командой подобной этой “rm -rf ./*”, удалять все добро нажитое непосильным трудом? Случалось? ))) Вот и я на днях допустил такой промах. Не посмотрел в какой директории находился и вместо очистки временного каталога, очистил каталог с проектами.

Решение

Из сложившейся ситуации я вынес урок – при удалении всегда нужно указывать полный путь. Таким образом вариант с удалением нужных данным будет сведен к минимуму.

Но все мы люди. А большинство людей ленивы. Поэтому вариант с полным путем не всегда пригоден. А стандартная утилита rm не удаляет файлы в корзину.

Исправим это:

sudo aptitude install trash-cli

потом добавил алиас:

vim ~/.bashrc

и добавляем строчку:

alias rm='trash'

рестартимся и готово: rm – помещает файлы в корзину!

Django widget calendar

Интро

В одном проекте, мне понадобился визуальный календарик. Брать “сторонние” разработки не хотелось, т.к. хороший календарик уже есть в админке Django. Осталось только его достать )

Легко?

Достать календарик проще простого:

from django import forms
from django.contrib.admin.widgets import AdminDateWidget

class TestForm(forms.Form):
    datefrom = forms.DateTimeField(label='Дата',  widget=AdminDateWidget)

Выглядит все просто и логично. Но, к сожалению этого не достаточно. Данному виджету трубуются дополнительные JS & CSS файлы.

Вначале я попытался сделать свой виджет унаследовав его от AdminDateWidget и дополнив его Meta-класс необходимыми js & css файлами. Но ничего не получилось, файлы подключались не в той последовательности.

Немного кода

# -*- coding: utf-8 -*-
import settings
from django import forms

class CalendarWidget(forms.TextInput):
    '''
    Данный виджет является, практически, копией
    django.contrib.admin.widgets.AdminDateWidget
    Но наследование от AdminDateWidget не удалось из-за неверного
    порядка JS-файлов в результирующем html, при наследовании.

    Для работы необходимо в urls.py добавить:
    (r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
    '''
    class Media:
        js = ('/admin/jsi18n/',
              settings.ADMIN_MEDIA_PREFIX + 'js/core.js',
              settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
              settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
        css = {
            'all': (
                settings.ADMIN_MEDIA_PREFIX + 'css/forms.css',
                settings.ADMIN_MEDIA_PREFIX + 'css/base.css',
                settings.ADMIN_MEDIA_PREFIX + 'css/widgets.css',)
        }

    def __init__(self, attrs={}):
        super(CalendarWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'})

Вот и весь код, но для корректной работы требуется подключение jsi18nurl.py):

urlpatterns += patterns('',
    (r'^admin/jsi18n/', 'django.views.i18n.javascript_catalog'),
)

Результат

P.S.

Примеры кода с другими реализациями данной задачи приветствуются!

Разукрасим SVN

Интро

Новый год для меня начался хорошо – я сменил работу и переехал в столицу нашей родины. А вместе с работой решил сменить и основную рабочую систему – с Windows XP на Ubuntu 9.10 )

Теперь приходится использовать SVN в консоли, т.к. nautilussvn, мягко говоря очень ограничен в функциональности, либо у меня просто не хватило терпения с ним разбираться.

Установка

  1. sudo aptitude install colordiff
  2. nano ~/.subversion/config
  3. находим параметр diff-cmd и прописываем diff-cmd = colordiff

Все, теперь svn diff будет цветным.
При использовании less не забудьте параметр -R:

svn diff | less -R

иначе less удалит раскасску.