25 декабря 2008 г.

Блоги о музыке, скачать музыку

Искал "Official Pirate" Маклафлина наткнулся на кучу блогов с отменной музыкой.
All music, All blogs - список музыкальных блогов
Блог фьюжен музыки
http://jazz-rock-fusion-guitar.blogspot.com/ - название говорит само за себя
Остальное, смотрите по первой ссылке, много всего!

24 декабря 2008 г.

Django. Валидация формсетов


def manage_authors(request):
AuthorFormSet = modelformset_factory(Author)
if request.method == 'POST':
formset = AuthorFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
# do something.
else:
formset = AuthorFormSet()
return render_to_response("manage_authors.html", {
"formset": formset,
})

Что происходит когда формсет не валидный?
формсет уже создан AuthorFormSet(request.POST, request.FILES).
Он и передается в render_to_response. Так что внимательнее, если вы передаете в него еще что-то.

21 декабря 2008 г.

Бердяев об эгоцентричности

Бердяев Н.А. Я и мир объектов:

Но "я" имеет свое существование лишь поскольку "я" трансцендирует себя, во внутреннем существовании своем выходит к другому и другим, к "ты", к другому человеку, к Божьему миру. Нет ничего противнее и разрушительнее, чем когда "я" эгоцентрически погружено в себя и свои состояния, забыв о других, о мире, о множественном и целом, т. е. не трансцендирует себя. Это свойство истерических женщин. Только лирический поэт может превратить это уродливое состояние в состояние прекрасное. Но поэтическое творчество есть уже трансцендирование. Основная проблема "я", которая бросает свет на все его существование, есть проблема одиночества, которая так мало исследована философски. Между тем как сама проблема познания может быть рассмотрена в перспективе проблемы одиночества и его преодоления и отсюда может быть добыт внутренний свет.


Что-то в этом есть.

19 декабря 2008 г.

attrs в виджетах django

В процессе написания мультивиджета, пришлось задуматься, а что такое attrs (атрибуты)? По началу было понятно, что это атрибуты поля формы:



Инициализация виджета (class Widget)

def __init__(self, attrs=None):
if attrs is not None:
self.attrs = attrs.copy()
else:
self.attrs = {}

Возьмем для примера следующий виджет:

class Select(Widget):
def __init__(self, attrs=None, choices=()):
super(Select, self).__init__(attrs)

В принципе понятно, что происходит. Далее, рассмотрим функцию рендеринга виджета:

def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [u'' % flatatt(final_attrs)]
options = self.render_options(choices, [value])
if options:
output.append(options)
output.append('')
return mark_safe(u'\n'.join(output))

Что делает функция build_attrs?

def build_attrs(self, extra_attrs=None, **kwargs):
"Helper function for building an attribute dictionary."
attrs = dict(self.attrs, **kwargs)
if extra_attrs:
attrs.update(extra_attrs)
return attrs

Функция принимает **kwargs (keyworded аргументы, то есть аргументы с ключами), в нашем случае передается ключ name с названием данного виджета. В итоге мы получаем примерно следующее:



Но откуда берется id?
Оно приходит в атрибутах до рендеренга виджета, из далеких глубин класса class BoundField(StrAndUnicode), который описан в исходниках как "A Field plus data".
Функция класса as_widget собственно и инициирует вызов рендеринга виджета.

def as_widget(self, widget=None, attrs=None, only_initial=False):
"""
Renders the field by rendering the passed widget, adding any HTML
attributes passed as attrs. If no widget is specified, then the
field's default widget will be used.
"""
if not widget:
widget = self.field.widget
attrs = attrs or {}
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
attrs['id'] = auto_id
if not self.form.is_bound:
data = self.form.initial.get(self.name, self.field.initial)
if callable(data):
data = data()
else:
data = self.data
if not only_initial:
name = self.html_name
else:
name = self.html_initial_name
return widget.render(name, data, attrs=attrs)

Поэтому, добавить свои атрибуты или получить данные из словаря в процессе переопределения рендеринга не сложно.

class MyWidget(forms.Select):
def render(self, name, value, attrs=None, choices=()):
id_ = attrs.get('id', None)
attrs.update({'onchange':'javascriptfunction(%s%s);' % id_,name})
return super(MyWidget, self).render(name, value, attrs)

Хотя можно передавать атрибуты и в определении самого виджета, функция self.build_attrs() просто обновит словарь новыми записями, но мне надо было именно переопределить атрибуты в виджете, для создания мультивиджета.
attrs.update() в мультивиджетах меняет атрибуты во всех подвиджетах.

18 декабря 2008 г.

Вывести значение поля формы в шаблоне

Вывести значение поля формы в шаблоне, вместо формы поля можно так:
{{ form.initial.field }}

16 декабря 2008 г.

Все проекты Django на Google Code

Ссылка:Все проекты Django на Google Code

Сменив label можно найти и другие полезные open source проекты на Google Code

wysiwyg редактор регулярных выражений

Нашел редактор регулярных выражений:
http://www.ultrapico.com/expresso.htm

Программа бесплатная, но надо заполнить форму, чтобы получить код, чтобы программа работала больше 60 дней.

Как получить traceback в django

Чтобы получить traceback в django, что бывает полезно, когда мы хотим посмотреть request информацию (django выдает куки, POST или GET данные) или сам трейс, в любом месте кода поместим:
assert False
или остановить в самом выражении и вывести его на верх трейса:
assert False, request.POST
assert False, form.cleaned_data['field_name']

Более подробно о дебаге в django (на аглийском).

Куда записывать с ip камеры D-Link DCS-950G?

Озаботился я темой как-то раз, имея камеру, хотелось записывать на внешний источник в интернет, но данное устройство позволяет писать только на NAS или сетевое устройство хранения информации (то есть, сетевую win папку), на ftp писать не может, как я понял (поправьте, если я не прав, я сильно не практиковался).
Так вот, не особо заморачиваясь поисками бесплатного NAS или win share, я все-таки нашел (точнее мне прислали ссылку), куда можно записывать данные:
http://skydrive.live.com/

Бесплатное хранилище объемом 25 ГБ в службе Windows Live
С помощью службы SkyDrive легко хранить и обмениваться файлами и фотографиями практически с любыми пользователем.


Microsoft любит нас =)))))

ps. Буду пробовать, пока нет времени.

15 декабря 2008 г.

queryset в поле формы

Продолжаем разбираться с формами. Имем такую форму:

festival = forms.ModelMultipleChoiceField(label=u'Посещенные фестивали',
required=False,
queryset=Festival.objects.all(),
)

Виджет ес-но не создает select.
Меня озаботило следующее.
А queryset действительно запрашивает все объекты базы или просто используется в виде Festival.objects.all().get(pk=355) .
И вообще, чем отличается Festival.objects.get(pk=355) и Festival.objects.all().get(pk=355) я пока не знаю.
Начинаем искать:

Что делает all()?
Во-первых - читаем документацию:
The all() method returns a QuerySet of all the objects in the database.

(If Entry.objects is a QuerySet, why can't we just do Entry.objects? That's because Entry.objects, the root QuerySet, is a special case that cannot be evaluated. The all() method returns a QuerySet that can be evaluated.)


Entry.objects, корень QuerySet - не может выдать данные. all() - возвращает объект QuerySet, который может выдать данные.

Далее код самой функции

def all(self):
return self.get_query_set()

def get_query_set(self):
"""Returns a new QuerySet object. Subclasses can override this method
to easily customize the behavior of the Manager.
"""
return QuerySet(self.model)

Возвращает новый объект QuerySet.

class QuerySet(object):
"""
Represents a lazy database lookup for a set of objects.
"""
def __init__(self, model=None, query=None):
self.model = model
self.query = query or sql.Query(self.model, connection)

Так query у нас нет, значит запрос выглядит так

# Use the backend's custom Query class if it defines one. Otherwise, use the
# default.
if connection.features.uses_custom_query_class:
Query = connection.ops.query_class(BaseQuery)
else:
Query = BaseQuery

Создается пустой BaseQuery. Далее:

class BaseQuery(object):
def __init__(self, model, connection, where=WhereNode):
self.model = model
self.connection = connection


А вообще, когда queryset возвращает данные, хорошо написано на странице When QuerySets are evaluated:

Internally, a QuerySet can be constructed, filter, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset.


То есть, не происходит никаких обращений к базе, при конструировании queryset'а .
Обращение к базе происходит при следующих запросах к queryset:

Iteration.

for e in Entry.objects.all():
print e.headline

Slicing.

Pickling/Caching.

repr().

len().

list(). Force evaluation of a QuerySet by calling list() on it. For example:

entry_list = list(Entry.objects.all())

Поэтому надо быть внимательным при множественных "вычислениях" queryset, в иных случаях использовать select_related, в других определять queryset единожды:

frndall=Friends.objects.all()#to cache qs
friends_ids=[f.id for f in frndall]
friends_names=[f.name for f in frndall]

но не

friends_ids=[f.id for f in Friends.objects.all()]
friends_names=[f.name for f in Friends.objects.all()]

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

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

fest_qs=Festival.objects.all()
queryset=fest_qs

, если нам требуется валидация значений по всей таблице для поля.

Формы в джанго

Даа, сложновато разобраться формами в django.
Этот топик - заметки в этапах ковыряния в исходниках и понятие структуры (может быть ошибочное мнение).
Итак,
1. форма содержит поля (fields).
2. в полях есть виджеты (widgets).

Инициализация формы:
Для вывода формы (а точнее преобразования значения поля из запроса в вид на форме), а также для обратного преобразования этих данных используются виджеты (которые используют данные instance или initial поля, а также POST данные).
Для проверки POST данных, преобразованных виджетом, используется метод clean поля (см ниже).

Вспомним, как мы сохраняем форму. Примерный процесс проверки POST данных:

if request.method == 'POST': # If the form has been submitted...
if form.is_valid():
# Process the data in form.cleaned_data
# ...
form.save()


Наша форма имеет предка - класс BaseForm, в котором есть функция is_valid():


def is_valid(self):
"""
Returns True if the form has no errors. Otherwise, False. If errors are
being ignored, returns False.
"""
return self.is_bound and not bool(self.errors)

Свойство is_bound:

self.is_bound = data is not None or files is not None

self.errors:

errors = property(_get_errors)

Метод свойства:

def _get_errors(self):
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors

А вот сама функция
 
def full_clean(self):
"""
Cleans all of self.data and populates self._errors and
self.cleaned_data.
"""
self._errors = ErrorDict()
if not self.is_bound: # Stop further processing.
return
self.cleaned_data = {}
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError, e:
self._errors[name] = e.messages
if name in self.cleaned_data:
del self.cleaned_data[name]
try:
self.cleaned_data = self.clean()
except ValidationError, e:
self._errors[NON_FIELD_ERRORS] = e.messages
if self._errors:
delattr(self, 'cleaned_data')

Метод clean поля:
 
class Field(object):
def clean(self, value):
"""
Validates the given value and returns its "cleaned" value as an
appropriate Python object.

Raises ValidationError for any errors.
"""
if self.required and value in EMPTY_VALUES:
raise ValidationError(self.error_messages['required'])
return value

Например, для поля CharField

def clean(self, value):
"Validates max_length and min_length. Returns a Unicode object."
super(CharField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = smart_unicode(value)
value_length = len(value)
if self.max_length is not None and value_length > self.max_length:
raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length})
if self.min_length is not None and value_length < self.min_length:
raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length})
return value

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

Моя задача: передать для одного поля ModelChoiceField динамический queryset, в зависимости от другого значения в POST данных (это нужно из-за того, что поле ModelChoiceField меняется динамически через AJAX, в зависимости от другого значения).
Изучив вышеприведенный код я нашел несколько путей для реализации:
1. Переопределив метод clean формы forms.ModelChoiceField
2. Передать в поле полный queryset, изменив виджет (чтобы он принимал наш "подставной" queryset), для вывода ограниченного числа значений.
3. Передавать нужный queryset в зависимости от data (то есть POST).

Последний вариант самый предпочтительный - самый простой, плюс доп проверка queryset, в зависимости от поля (сохранится структура базы) и у меня работает)

11 декабря 2008 г.

Преобразование словаря в строку в Python

Вот собственно:

";".join(["%s=%s" % (k, v) for k, v in params.items()])

params - словарь.
; - разделитель между элементами словаря
= - разделитель между парами ключ\значение.

Все просто =)

9 декабря 2008 г.

Создание блочной структуры, выборка блока по маске в зависимости от текущего url в django

Для реализации структуры статических блоков, содержание которых хранится в базе данных, а вывод регулируется в зависимости от текущего url надо, чтобы наш url входил в регулярное выражение для данного блока.
Модель блока простая, указывать не буду.

Чтобы было понятнее, логика обратная следующей

Block.objects.get(path_mask__contains='url')

Здесь идет поиск по полю path_mask, содержащему 'url'.
Нам же надо найти объект, для которого значение 'url', содежит path_mask.

Код для регистрации inclusion_tag

import re

@register.inclusion_tag("show_block.html")
def show_left_blocks(url):
blocks = Block.objects.filter(column="left", active=True)
blocks_out = []
for block in blocks:
path_r=re.compile(block.path_mask)#создаем регулярное выражение
if path_r.search(url): #ищем в строке url совпадение
blocks_out.append(block) #если есть совпадение - добавляем блок
return {'blocks': blocks_out}


Минусы:
-приходится запрашивать все блоки, поиск идет на уровне приложения а не базы
(в принципе не особо критично, т.к. блоков даже в крупных проектах не сотни тысяч)

ps. Может я просмотрел, и джанго может сама выполнять данную работу на уровне базы?

8 декабря 2008 г.

Прерывание перехода по ссылке "#" в javascript

Переход по ссылке при обработке ее яваскриптом нам не нужен. Например, при:

link

Почему не нужен? Потому что в адресной строке # нам ни к чему, плюс некоторые браузеры (фаерфокс, ie) выполняют переход по новой ссылке без перезагрузки страницы, что приводит по крайней мере к потере позиции скроллинга страницы.
Посему возвращаем false , тем самым прерывая переход по ссылке:

link

Немного разобрался с созданием форм из моделей

Думал раньше, что если instance содержит данные, значит редактирование, если нет, значит новая запись.
Однако это еще не все. Должна быть data:

f = Form(data=request.POST, instance=a)

Именно поэтому в инете очень много вопросов, почему при создании формы из модели при существующем instance не проходит валидация формы, да потому что данных для валидации при единственном instance на самом деле нет.

О чем я начал тему: http://softwaremaniacs.org/forum/django/7303/

2 декабря 2008 г.

Два formset'а в одном виде, дополнительное отображение

Все задачи без детального продумывания и без идеального знания Питона (или Пайтона).
Это скорее заметки для себя, а не руководство.


Первая ласточка: есть поле manytomany с аргументом through

class Person(models.Model):
name = models.CharField(max_length=128)

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()

Надо сделать одновременную форму для редактирования Группы и Членства для персоны.
И Членство для Персоны может быть не одно.
Считая, что у нас есть инстанс персоны, создаем два формсета (можно использовать inline_formset для каждого, а можно не использовать, нет разницы, по-моему (лишь использование instance вместо queryset, чего можно добиться просто изменив запрос):

Как создаются формсеты рассказывать не буду. В документации все подробно расписано. Будем создавать формсет на основе модели.
Итого: у нас два одинаковых формсета (в одном Членство, в другом Группа для этого членства). Но нам надо редактировать каждую форму данных формсетов вместе.

Вот простое решение как подружить два формсета, плюс добавить в счетчик.
Добавляем во view:

class MergeForm(object):
def __init__(self, groupform, memebershipform,index):
self.groupform=groupform
self.memebershipform=memebershipform
self.index=index

output=[]
idx=0

for group_form in groupformset.forms:
memebership_form=memebershipformset.forms[idx]
output.append(MergeForm(group_form, memebership_form, idx+1))
idx+=1

Передаем в render_to_response два формсета и наш объект output.

Ну а управление дополнительными формами я планирую вести с помощью jquery

24 ноября 2008 г.

Django

Начал тут работать с сабжем. Очень понравилось.
Если будет желание и время, опубликую не очевидные, но приятные решения. Хотя сам сейчас такие ищу в инете и разбираюсь.

Какая же дрянь эта sape.ru, setlinks.ru рулит

Сабж, почему все на него лезут - не понимаю.
Недавно зарегился снова...
Почему снова? Да потому что где-то около года назад хотел воспользоваться. Зарегистрировался, пока настроил, дождался ссылок. когда пришли ссылки, решил зайти в интерфейс, что-то поправить (уже не помню) - а вот фиг вам! Не пускает! Проныкался месяца два - писал в техподдержку и на форум - ничего не сделали.

Так вот, зарегился снова (думал может исправились). Оформил площадку, странички берутся из индекса Яндекса (это сразу насторожило). Ну ладно думаю, пускай. Оформил все - странички в ОК, с пятницы по понедельник ждал модерации (у них модерация, да еще и с выходными - о, 21 век!). Дождался - "не прошел модерацию".
Почему, зачем?
Логика нормального человека - извещения (ну думаю тут должно быть что-то написано) - неа, пусто.
Потыкал на площадку - никаких комментариве не нашел. Пошел в Faq. Там что-то по поводу яндекса. Если странички не в Яндексе - не примем. Но постойте? Вы же брали их откуда? Ну если сами индексировали зачем вам яндекс, а если брали с яндекса то в чем проблема?
Как проверить что страица в яндексе? - есть кнопочка около каждой страницы - по нажатии на нее - переход на линк с проверкой - если ли страница в индексе яндекса? Мухаха, даже на моем небольшом сайтике 2000 страниц, дануеенафиг)
Удалил, забыл как страшный сон. Да здравствует Сетлинк.

ps. С setlinks.ru ну никаких проблем (ну падал сервер недавно, ну и что, подняли починили, все хорошо, я даже не заметил ничего), видно что писали более менее адекватные программисты, с поддержкой общался - все на хорошем уровне.

7 августа 2008 г.

Понимание ценности человека

Пришла в голову мысль, что все очень сложно в этом мире. Ну это я знал конечно и до этого. А мысль очень простая. Есть человек, он так-то поступает и живет вот так-то. Так вот, ценности данного человека не в том, какой у него такой характер (назовем это так, в общем, имеется ввиду вся совокупность человека, не зависимая от человека, а зависимая от природы, от ген и т.п.), а в какую сторону и на сколько он смог его побороть. Исходя из этого, людям со скверным характером, стать понимающими и добрыми - намного труднее, чем со склонными к этому людьми. Соотвественно, это большая ценность, чем стать еще добрее и так доброму человеку. Ценность стала понятна, осталось выяснить а что дает нам эта ценность?

3 апреля 2008 г.

Установка Eclipse 3.3.2 на debian etch 86_64

Eclipse - IDE для прграммирования, написанная на java. Для установки свежей версии на 64 битном etch, используя java-package из коробки нужны небольшие хитрости.
1. Устанавливаем java-package.
2. от root:

cd /usr/share/java-package
cp -a sun-j2re1.5 sun-j2re1.6

редактируем sun-j2re1.6/install
первая строка: suffix=j2re1.6-sun

редактируем sun-j2re.sh
добавляем в секцию amd64|x86_64-linux-gnu

"jre-6-linux-amd64.bin")
j2se_version=1.5
j2se_expected_min_size=16 # 16542512 bytes
found=true
;;


Сохраняем и выходим.

3. качаем jre-6-linux-amd64.bin с sun.com
4. заходим под обычным пользователем и сохраняем бинарный файл в домашнюю директорию
5. выполняем $fakeroot make-jpkg jre-6-linux-i586.bin
6. удаляем пакеты gij и SableVM из системы.
7. проверяем $java -version
8. распаковываем и просто запускаем Eclipse.