21 июня 2013 г.

django: QuerySet расширяемый Manager

Приспособился использовать небольшой QuerySetManager для удобства добавления налету методов в QuerySet модели. Т.е. просто прописыванием в классе модели соответствующий QuerySet расширяется, довольно удобно, если надо писать сложные менеджеры для модели. Сам класс выглядит так:
from django.db import models

class QuerySetManager(models.Manager):
    def get_query_set(self):
        return self.model.QuerySet(self.model)

    def __getattr__(self, attr, *args):
        return getattr(self.get_query_set(), attr, *args)
Внутрь класса где-то рекомендовалось добавить полем "use_for_related_fields=True", но работает без него. Зато не работает без __getattr__, пишет: 'RelatedManager' object has no attribute 'useractive', вопреки ещё какой-то рекомендации из инета. В итоге имеем некий хак.

Используется как-то так:
class Clazz(models.Model):
    ...
    objects = QuerySetManager()
    ...
    class QuerySet(models.query.QuerySet):
        def useractive(self,date):
            return self.filter( Q(active=True) & (Q(date__isnull=True)|Q(date__gte=date)) )
И потом во вьюшках:
Clazz.objects.useractive(now).order_by('date')

30 мая 2013 г.

django: отправка email шаблонами из FlatPage

Приспичило сделать в django отправку email с удобной настройкой формата(-ов) письма. Понятно, что при этом должны работать какие-то переменные в шаблоне, куда удобно подставится что-то заранее предусмотренное. Ну и придумал для этого использовать FlatPage, которые идут «искаропки» и уже нормально редактируются в админке (я прикрутил туда ещё и TinyMCE). Плюс надо бы письма слать в формате html, для пущей красоты.

20 мая 2013 г.

django: минимальное количество formset inline

Захотелось мне в django, чтобы formset содержал не менее некоторого количества полностью заполненных форм. С нормальной валидацией где нужно, а не в середине вьюшки, например. На момент 1.4.x ничего особо удобного на этот счёт не было (возможно, это странно), хотя какие-то реквесты в багзилле я находил. На самом деле довольно просто ручками всё решается наследованием и переопределением InlineFormSet при конструировании FormSet через factory (а я так использую всегда).

Допустим, мы конструируем FormSet таким образом (обратите внимание на formset=...):
ConductingClazzRequestMorePersonFormSet = inlineformset_factory(ConductingClazzRequest, ConductingClazzRequestPerson, extra=1, formset=ConductingClazzRequestPersonFormsetBase, form=ConductingClazzRequestPersonForm)

17 апреля 2013 г.

Баг в camera slideshow при одном слайде

Использовал довольно приятную крутилку баннеров (слайдшоу) camera slideshow (http://www.pixedelic.com/plugins/camera/). Но один косяк очень сильно напрягал всё время — при единственном слайде работает некорректно: показ этого слайда перемежается показом пустого слайда.

14 апреля 2013 г.

django: не разрешать формам в formset быть пустыми

В django при использовании formset по умолчанию* действует такая штука: при сохранении всего formset незаполненные формы (полностью незаполненные) в нём игнорируются и валидируются/сохраняются только остальные. Если по какой-то причине это неудобно (у меня, например, нужно было заполнять минимум N форм в формсете), то можно отключить, установив empty_permitted = False.

* На самом деле ставится некоторым (extra) формам при конструировании formset, что в общем-то логично.

В документации на этот счёт сказано: «The formset is smart enough to ignore extra forms that were not changed».

Можно намертво прописать в конструкторе формы, например.
class BlablaForm(forms.ModelForm):
    class Meta:
        model = Blabla

    def __init__(self, *arg, **kwarg):
        super(BlablaForm, self).__init__(*arg, **kwarg)
        self.empty_permitted = False

7 апреля 2013 г.

Самодельный упрощённый accordion на jquery

Нужна была схлопывалка дивов, с заголовками, раскрывающая содержимое по очереди. Изначально был код на jquery-ui через accordion, но мучение со стилями достало. Т.к. стили наворачиваются хардкорно, а переопределять все в css получается в несколько раз длиннее, чем сам код.
$( "#accordion" ).accordion({
  active: false,
  collapsible: true,
  header: ".accordion_later",
  heightStyle: "content",
  beforeActivate: function( event, ui ){
   ui.newHeader.hide();
   ui.oldHeader.show();
  }
 });
Рабочий пример: http://jsfiddle.net/Fx4nA/
Потом переделал тупо на jquery, получилось в несколько раз короче.
$('#accordion .collapsible').hide();
$('#accordion .accordion_later').bind('click', function (e) {
    // show all "more..."
    $('#accordion .accordion_later').show();
    // close all collapsible
    $('#accordion .collapsible').slideUp();
    // hide current "more..."
    $(e.target).hide();
    // open current collapsible
    $(e.target).next('div').slideDown();       
});
Рабочий пример: http://jsfiddle.net/8qtXH/

5 апреля 2013 г.

jquery ui dialog без заголовка

Убрать заголовок можно переопределив класс ui-dialog-titlebar, но чтобы не испортить все диалоги сразу можно выборочно через dialogClass.
dialogdiv.dialog({
...
    dialogClass: 'dialog-wo-title',
...

Потом скрываем и всё.
.dialog-wo-title .ui-dialog-titlebar
{
    display:none;
}
Или убираем всё кроме кнопки закрытия (которая остаётся справа)
.dialog-wo-title .ui-dialog-titlebar
{
    width: 0px;
    float: right;
}