Моя библиотека - социальная сеть любителей книг

Роботы

Программирование, Разное 03.08.2010

Интро

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

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

И так… Читать полностью »

Django 1.2.1 и load_related_m2m

Программирование 18.07.2010

Интро

Думаю, многие из нас занимались оптимизацие загрузки данных из полей 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 )

Django widget calendar

Программирование 10.02.2010

Интро

В одном проекте, мне понадобился визуальный календарик. Брать “сторонние” разработки не хотелось, т.к. хороший календарик уже есть в админке 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.

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

Django & WYSIWYG

Программирование 31.08.2009

Интро

Я по прежнему продолжаю изучать Django + Python. Пока этот тандем не перестает меня радовать. И все больше усилий мне приходится делать над собой, чтобы разрабатывать на работе на PHP с использованием самописного фреймворка.

И вот, на одном из сайтов понадобился WYSIWYG-редактор.
Читать полностью »

Django & Cron

Программирование 15.04.2009

Интро

В предыдущей статье я описывал как выкладывать Django-проект на сервер и можно сказать попутно выкладывал. =) Но на этом мои “мучения” не закончились - оказалось, что я не знаю как прикрутить вызовы частей приложения по Cron.

Погуглив и почитав, решение нашлось… и оно оказалось намного приятнее решения на php ;)

Решение

В корневой директории проекта, в моем случае publishing, создаем фалик run.py:

# -*- coding: utf-8 -*-
import sys
import settings
from django.core.management import setup_environ
setup_environ(settings)
module_name = sys.argv[1]
exec('import %s' % module_name)
exec('%s.%s' % (module_name, ' '.join(sys.argv[2:])))

Update: Спасибо Александру Кошелеву за ценный комментарий.

И теперь при помощи этого скрипта мы можем вызывать функции наших “вьюшек” из командной строки и из cron:

# python /path/to/project/run.py report.views "send_emails()"

Таким образом у нас выполниться report.views.send_emails()
Все, остается вызвать crontab -e и добавть выше описанную команду.

Как всегда, все просто. =)


Copyright, 1983 – 2010