Возникла задача в одном из моих django-проектов предоставить API для взаимодействия с некоей внешней системой.
Первоначальный выбор пал на django-piston. Реализовать операции read-доступа к объектам БД удалось довольно быстро, но вот с операцией создания объекта начались проблемы, частично решив которые и получив новые , решил выбрать другое решение.. Уж больно надоело патчить чужую библиотеку.
Другое решение - это Django Rest Framework. Знакомство с отзывами и документацией обещает менее нервную разработку. К непосредственной попытке использования приступлю на днях.
Постараюсь не забыть задокументировать здесь все особенности и подводные камни, если таковые найдутся :)
четверг, 4 июля 2013 г.
среда, 29 мая 2013 г.
django: форма обратной связи с аттачами и проверкой на вирусы
Предыстория
Недавно получил от одного своего постоянного клиента заказ на следующую доработку: "нужно доработать форму обратной связи для возможности отправки файлов клиентами".В процессе обсуждений выяснилось, что файлов надо аттачить "сколько хочешь".
А чтобы заказчик не "словил вирусняк" через эти самые аттачи , я решил реализовать сканирование.
Было 2 варианта:
- настроить на серваке (linux) какой-нибудь , желательно бесплатный , антивирусный демон
- использовать API какого-нибудь авторитетного онлайн сервиса
Я остановился на втором варианте, тем более что был немного знаком с Virustotal.
Бегло ознакомился с доками на его API .
Проверил работоспособность его тестовых примеров - все ок.
И приступил к "допиливанию" имеющейся формы обратной связи.
Как только причешу код , чтобы было не стыдно опубликовать на bitbucket, то детально опишу реализацию.
Кому не терпится - пишите, торопИте :)
понедельник, 29 апреля 2013 г.
django-lfs: особенности работы со скидками
Текущая стабильная версия 0.7.7
В django-lfs есть два механизма работы со скидками:
В django-lfs есть два механизма работы со скидками:
- назначать скидку каждому товару отдельно в карточке товара
- создавать глобальные скидки, которые действуют в зависимости от критериев (например общая сумма покупки в корзине) - данные скидки применяются не к отдельным товарам , а к всему содержимому корзины.
Особенность в том, что при наличии обоих скидок они суммируются.
При использовании данной и более младших версий django-lfs вместе с django >= 1.4 есть проблема с интерфейсом управления - а именно бага при работе с критериями. Суть ошибки и как ее решить я уже описывал здесь.
Кроме того, глобальным ссылкам не хватает развернутого описания . Например, для того, чтобы вывести страницу со скидками, где было бы содержательно описана суть каждой из них.
Доработать не трудно.
- добавляем нужное поле в Discount
- добавляем колонку в таблицу discount_discount (если база уже существует) или пересоздаем базу (если старого контента не жалко :)
- добавляем нужный html-шаблон для страницы со списком скидок
- добавляем view, которая будет рендерить этот шаблон
- добавляем url, по которому это view будет "дергаться"
кому нужен патч - пишите.
пятница, 12 апреля 2013 г.
django-lfs: установка на Windows 7
Установка django-lfs подробно описана здесь
Но у установки под windows есть несколько особенностей, которые не описаны на официальном сайте
Исходные данные:
Но у установки под windows есть несколько особенностей, которые не описаны на официальном сайте
Исходные данные:
- windows7 64 bin
- python 2.7 , установленный , например в c:\Python27
Требуется установить django-lfs (на текущий момент версия 0.7.7)
- качаем инсталлятор http://pypi.python.org/pypi/django-lfs
- распаковываем куда нам нужно
- cd lfs-installer
- качаем правильный bootstrap.py
- python bootstrap.py
- качаем win-инсталлятор для библиотеки PIL (так как установщик ругнется на отсутствие батника vcvarsall.bat)
- создаем ключ в реестре HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Python\PythonCore\2.7\InstallPath со значением, которое копируем из ключа HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.7\InstallPath - без этой манипуляции инсталлятор PIL "ругнется" Python27 not found
- удаляем Pillow из списка зависимостей djanfo-lfs (файл: lfs-installer\eggs\django_lfs-0.7.7-py2.7.egg\EGG-INFO\requires)
- устанавливаем PIL
- bin/buildout.exe -v
- указываем параметры доступа к базе данных (предполагается, что она уже создана) в settings to lfs_project/settings.py
- $ bin/django syncdb
- $ bin/django lfs_init
- $ bin/django collectstatic
- $ bin/django runserver
- Открываем дефолтный магазин http://localhost:8000 и торгуем :)
пятница, 29 марта 2013 г.
django-lfs: wysiwyg и копипаст контента с других сайтов
В каждом новом веб-проекте встает дилемма - использовать ли wysiwyg в административной части сайта. С одной стороны хочется избавить себя от будущего утомительного контент-менеджмента, который не очень дорого оплачивается (если вообще оплачивается), а с другой - дашь пользователю полноценный wysiwyg - он вмиг сломает всю верстку и в итоге тебя же и обвинит: "ты мол программист, ты должен был все учесть"...
Каждый раз приходится анализировать, что за пользователи будут рулить сайтом, обучать даже иногда.
В общем это проблема не новая. Есть еще одна - смежная с ней. Часто начинающие "контент-менеджеры" сайтов (они же и их владельцы по-совместительству :) не брезгуют простым копипастом контента с сайтов конкурентов, сайтов с понравившимся контентом.. Им невдомек, что есть понятие "копирайт", что редактор "не умеет" превращать чужие картинки в свои, что он копирует буквально все, в том числе и внешние ссылки.
Один такой мой клиент, пользующийся интернет-магазином на django-lfs, ну никак не хотел бросать такую вредную привычку , пришлось запилить ему логику дайнлоада картинок из скопированного куска, вычистку непредусмотренных внешних ссылок .
Везде , где можно был переопредлен обработчик save моделей и в этом обработчике вызывался метод, который скачивает картинки в media, меняет пути на свои локальные, чистит внешние ссылки.
Планирую еще и PIL прикрутить к этому делу, чтобы вотермарки накладывать. Любой каприз, как говорится, за ваши деньги.
p.s. но тырить контент с чужих сайтов, не оставляя ссылок - нехорошо , о чем все мои клиенты честно предупреждаются.
p.p.s если кого интересует, то могу код причесать и выложить на какой-нибудь bitbucket - пишите.
Каждый раз приходится анализировать, что за пользователи будут рулить сайтом, обучать даже иногда.
В общем это проблема не новая. Есть еще одна - смежная с ней. Часто начинающие "контент-менеджеры" сайтов (они же и их владельцы по-совместительству :) не брезгуют простым копипастом контента с сайтов конкурентов, сайтов с понравившимся контентом.. Им невдомек, что есть понятие "копирайт", что редактор "не умеет" превращать чужие картинки в свои, что он копирует буквально все, в том числе и внешние ссылки.
Один такой мой клиент, пользующийся интернет-магазином на django-lfs, ну никак не хотел бросать такую вредную привычку , пришлось запилить ему логику дайнлоада картинок из скопированного куска, вычистку непредусмотренных внешних ссылок .
Везде , где можно был переопредлен обработчик save моделей и в этом обработчике вызывался метод, который скачивает картинки в media, меняет пути на свои локальные, чистит внешние ссылки.
Планирую еще и PIL прикрутить к этому делу, чтобы вотермарки накладывать. Любой каприз, как говорится, за ваши деньги.
p.s. но тырить контент с чужих сайтов, не оставляя ссылок - нехорошо , о чем все мои клиенты честно предупреждаются.
p.p.s если кого интересует, то могу код причесать и выложить на какой-нибудь bitbucket - пишите.
суббота, 23 марта 2013 г.
Хостинг jino и bitbucket
Не хочу давать ни рекламы , ни антирекламы , но у меня возникает следующая проблема с хостингом jino.
Клонирование репозитория с bitbucket в данный момент невозможно, так как hg clone отваливается по tcp-таймауту. Проблема перманентная, то есть не связана с какими-то временными трудностями на любой из сторон.
Вариант с клонированием через ssh не проходит, так как на jino нет ssh-клиента.
Вот и приходится обновлять исходники через третий сервер (
Саппорт пока не ответил на просьбу устранить эту проблему или вообще объясить как-то причину .
Ждем.
Клонирование репозитория с bitbucket в данный момент невозможно, так как hg clone отваливается по tcp-таймауту. Проблема перманентная, то есть не связана с какими-то временными трудностями на любой из сторон.
Вариант с клонированием через ssh не проходит, так как на jino нет ssh-клиента.
Вот и приходится обновлять исходники через третий сервер (
Саппорт пока не ответил на просьбу устранить эту проблему или вообще объясить как-то причину .
Ждем.
понедельник, 4 марта 2013 г.
lightbox vs elastislide
В одном из веб-проектов потребовалось реализовать галерею изображений.
Ранее уже успешно использовал плагин jquery.elastislide.js.
Применил и на этот раз.
Кроме того, надо было сделать так, чтобы по клику на фотку она открывалась в "полный рост" - наиболее популярным решением сейчас является для этого lightbox , его я и попытался применить.
Все сделал по манам, верстка правильная, ошибок в консоли js нет, но изображение по клику не открывается - lightbox не фурычит.
Сразу заподозрил конфликт обработчиков событий. Так и оказалось.
Чтобы его преодолеть в опциях создания слайдера необходимо обнулить обработчик onClick изображений:
Ранее уже успешно использовал плагин jquery.elastislide.js.
Применил и на этот раз.
Кроме того, надо было сделать так, чтобы по клику на фотку она открывалась в "полный рост" - наиболее популярным решением сейчас является для этого lightbox , его я и попытался применить.
Все сделал по манам, верстка правильная, ошибок в консоли js нет, но изображение по клику не открывается - lightbox не фурычит.
Сразу заподозрил конфликт обработчиков событий. Так и оказалось.
Чтобы его преодолеть в опциях создания слайдера необходимо обнулить обработчик onClick изображений:
$('#carousel').elastislide({imageW :300,margin: 30,minItems: 2, onClick: null});воскресенье, 24 февраля 2013 г.
Небольшая ремарка по django-imagestore
Тому, кто хочет организовать фотогалерею на django, могу посоветовать в качестве основного приложения django-imagestore .
Приличный функционал, возможность расширения засчет переопределения моделей альбомов и фотографий, более-менее удобная админка.
Но как всегда не без греха. Как минимум одна проблема в этом модуле есть - а именно проблема каскадного удаления..
Допустим, у вас есть альбом, в нем много фотографий.
Вы из админки удаляете фотографию (не выключаете из альбома, а просто удаляете).
Мелким шрифтом , конечно, показывается предупреждение о том, что будут удалены все сущности. Но кто их читает ?)
Вот и получается - хотели удалить фотку, а удалили весь альбом.
А если на альбом ссылалась еще какая-нибудь сущность, то и она успешно удалится.
На подобное я напарывался в django-lfs.
Чтобы решить эту проблему , необходимо либо пропатчить поле Image.album, добавив в него on_delete=models.SET_NULL.
Либо переопределить Image , как это позволяет делать imagestore и уже аналогично решить эту проблему на уровне своей модели.
Приличный функционал, возможность расширения засчет переопределения моделей альбомов и фотографий, более-менее удобная админка.
Но как всегда не без греха. Как минимум одна проблема в этом модуле есть - а именно проблема каскадного удаления..
Допустим, у вас есть альбом, в нем много фотографий.
Вы из админки удаляете фотографию (не выключаете из альбома, а просто удаляете).
Мелким шрифтом , конечно, показывается предупреждение о том, что будут удалены все сущности. Но кто их читает ?)
Вот и получается - хотели удалить фотку, а удалили весь альбом.
А если на альбом ссылалась еще какая-нибудь сущность, то и она успешно удалится.
На подобное я напарывался в django-lfs.
Чтобы решить эту проблему , необходимо либо пропатчить поле Image.album, добавив в него on_delete=models.SET_NULL.
Либо переопределить Image , как это позволяет делать imagestore и уже аналогично решить эту проблему на уровне своей модели.
воскресенье, 17 февраля 2013 г.
Слайды: кастомизация интерфейса django-admin
На просторах интернета попалась следующая презентация, которая может задать вектор начинающему джанговоду в направлении того, как можно изменить стандартный интерфейс админки django.
Не могу не поделиться
Не могу не поделиться
вторник, 12 февраля 2013 г.
How to improve Test::Class to conrol test ttl
To make Test::Class control test-suites time-to-live you could inherit Test::Class and redefine runtests method..
For example:
I think, we don't need SIGCHILD here..
source
For example:
package TTL::Test::Class;
use base qw(Test::Class);
use Test::More;
use POSIX ":sys_wait_h";
use constant DEFAULT_TIMEOUT => 60;
# переопределяем метод запуска тестов
sub runtests{
my $t = DEFAULT_TIMEOUT;
my $pid = fork;
my $child_ret_code;
if( $pid > 0 ){ # parent process
#child waiting loop
my $ok_flag = 0;
for(my $i=0; $i < $t; $i++){
if(waitpid($pid, WNOHANG)){
$child_ret_code = $?/256;
ok($child_ret_code);
$ok_flag = 1;
last;
};
sleep(1);
};
if( not $ok_flag ){
diag "Killing test by its timetolive...";
kill TERM =>
$pid;
return $ok_flag;
};
return $child_ret_code;
} elsif( $pid == 0 ) { #child
exit $self->SUPER::runtests;
} elsif ( not defined($pid) ) { #unsuccessfull fork
die "Cannot fork child process: $!";
}
}
1;
I think, we don't need SIGCHILD here..
source
Подписаться на:
Сообщения (Atom)