Сегодня попросили запилить виджет ВКонтакте для отображения ифрейма одной из ВК-групп.
Ранее это я делал сотни раз - ну примитивнейшая задачка, которая сводится лишь к небольшому копипасту.
Подключил нужный openapi.js от ВКонтакте.
Поместил нужный код (div+script) в нужное место нужного сайдбара и обновил страницу.
Увидел два идентичных блока с данными группы.
"Ха, ерунда" , подумал я , будучи уверен, что скопировал лишний div или что-то вроде того...
Увидился, когда код оказался в порядке. И началось... Ну сплошная мистика - откуда второй блок - неясно.
Забегая вперед - на пальцах и сейчас не объясню , откуда... Но в итоге нашел "виновника"...
На данном сайте используется CSS - фреймворк Kickstart. Довольно практичная и удобная штука, надо сказать. Ну так вот. Этот фреймфорк идет вместе со своим js-тулкитом, в котором заплен функционал для простеньких слайдшоу, некоторая хитрая работа с DOM и т.д.
Файл подключен в <head>. В консоль ошибками не плюется. Сам фреймворк отлажен и пользуется популярностью у существенного количества людей. Но вот ВКонтактовский виджет зачем-то клонирует)
В итоге пришлось <script> , рисующий вконтактовский ифрейм помещать непосредственно перед </body> , чтобы не дать никому шанса все испортить...
Виджетов теперь ровно столько, сколько надо - один :)
p.s. какой именно код kickstart.js все испохабил я пока не понял.. будет время (а это врядли ) - раскопаю :)
пятница, 20 апреля 2012 г.
среда, 18 апреля 2012 г.
django: совместимость с 1.4 : settings.py - ImproperlyConfigured: Error importing template source loader
В продолжении предыдущего поста о совместимости с django 1.4
Может возникнуть следующая проблема с загрузкой шаблонов при рендеринге:
Решение: закомментировать TEMPLATE_LOADERS в settings.py и скопипастить аналогичные настройки из settings.py , сгенерированного django-admin от версии 1.4
Может возникнуть следующая проблема с загрузкой шаблонов при рендеринге:
ImproperlyConfigured: Error importing template source loader django.template.loaders.app_directories.load_template_source: "'module' object has no attribute 'load_template_source'"
Решение: закомментировать TEMPLATE_LOADERS в settings.py и скопипастить аналогичные настройки из settings.py , сгенерированного django-admin от версии 1.4
django: совместимость с 1.4 : diario - ImportError: No module named feeds
Не так давно вышел официальный релиз django 1.4
До его выхода кто-то дальновидно заранее начинал работать с пре-релиз версией и портировать на нее свои существующие проекты.
Те, кто предпочел использовать в повседневновсти стабильную версию 1.3 теперь либо продолжают ее использовать, либо потихоньку (ведь никто не гонит) , переводят проекты на 1.4.
При этом у каждого НЕИЗБЕЖНО возникнут большие и малые трудности..
Дело в том, что весь зоопарк сторонних django-приложений еще не успел актуализироваться вслед за измененями в django, которые появились в версии 1.4
В этом и быть может последующих постах буду более менее существенные моменты отражать - быть может этот опыт пригодиться кому-то быстрее решить проблему миграции..
1. django-diario - неплохое приложение для организаци блога. В нем я наткнулся на ошибку импорта в 13-й строке файла diario/feeds/entries.py:
Проверил - в текущей версии diario проблема не решена , поэтому пришлось пока "ручками" поправить.
2. еще одно замечание про diario
Из-за того же рефакторинга django.contrib.syndication изменился и способ работы с фидами, которые предоставляет diario.
Если раньше вы подключали url-ы для фидов примерно так:
то теперь это надо делать так:
Удачи!
До его выхода кто-то дальновидно заранее начинал работать с пре-релиз версией и портировать на нее свои существующие проекты.
Те, кто предпочел использовать в повседневновсти стабильную версию 1.3 теперь либо продолжают ее использовать, либо потихоньку (ведь никто не гонит) , переводят проекты на 1.4.
При этом у каждого НЕИЗБЕЖНО возникнут большие и малые трудности..
Дело в том, что весь зоопарк сторонних django-приложений еще не успел актуализироваться вслед за измененями в django, которые появились в версии 1.4
В этом и быть может последующих постах буду более менее существенные моменты отражать - быть может этот опыт пригодиться кому-то быстрее решить проблему миграции..
1. django-diario - неплохое приложение для организаци блога. В нем я наткнулся на ошибку импорта в 13-й строке файла diario/feeds/entries.py:
from django.contrib.syndication.feeds import Feed
ImportError: No module named feeds
Действительно, в версии 1.4 нет файла feeds - вместо него используется views - видимо так правильнее ) Имена сущностей те же.. то есть, теперь надо
from django.contrib.syndication.views import Feed
Проверил - в текущей версии diario проблема не решена , поэтому пришлось пока "ручками" поправить.
2. еще одно замечание про diario
Из-за того же рефакторинга django.contrib.syndication изменился и способ работы с фидами, которые предоставляет diario.
Если раньше вы подключали url-ы для фидов примерно так:
from diario.feeds.entries import RssEntriesFeed, AtomEntriesFeed
entries_feeds = {
'rss': RssEntriesFeed,
'atom': AtomEntriesFeed,
}
#...
urlpatterns = patterns(
url(r'^pub/(?P(rss|atom))/$', 'django.contrib.syndication.views.feed', {'feed_dict':
entries_feeds}),
)
то теперь это надо делать так:
from diario.feeds.entries import RssEntriesFeed, AtomEntriesFeed
#...
urlpatterns = patterns(
url(r'^pub/(?Prss)/$', RssEntriesFeed()),
url(r'^pub/(?Patom)/$', AtomEntriesFeed()),
)
Удачи!
среда, 28 марта 2012 г.
BOOTSTRAP CSS FRAMEWORK: проблема с carousel ( Cannot read property 'end' of undefined)
Использую в одном из проектов css-фреймворк bootstrap от twitter.
Вчера обнаружил очередное обновление, вместе с которым появился js-плагин для слайдшоу.
Подключил его отдельным скриптом bootstrap-crousel.js и при прокрутке первого же тестового элемента слайдшоу получил ошибку в js-консоли:
Немного попыхтев обнаружил, что этот плагин не совсем самостоятелен и зависит от других плагинов этого фреймворка.
В частности от bootsrap-transitions.js.
Пришлось подключить и его.
А вообще , проще всего подключить весь bootstrap.js во избежание подобных багов в будущем.
Вчера обнаружил очередное обновление, вместе с которым появился js-плагин для слайдшоу.
Подключил его отдельным скриптом bootstrap-crousel.js и при прокрутке первого же тестового элемента слайдшоу получил ошибку в js-консоли:
Cannot read property 'end' of undefinedсо ссылкой на 109 строку bootstrap-carousel.js
Немного попыхтев обнаружил, что этот плагин не совсем самостоятелен и зависит от других плагинов этого фреймворка.
В частности от bootsrap-transitions.js.
Пришлось подключить и его.
А вообще , проще всего подключить весь bootstrap.js во избежание подобных багов в будущем.
четверг, 22 марта 2012 г.
nginx: unknown directive "uwsgi_pass"
Постепенно начинаю отказываться от apache как основного веб-сервера для своих проектов.
Альтернатива? Буду банален - nginx.
Решил описывать все камушки, каменюги , грабли и грабельки , на которые буду наступать в ходе освоения этого броузера.
Итак, первая "проблема":
На Debian 6 установил nginx из репозитория .
Настроил на взаимодействие с django проектом через uwsgi.
Первый запуск веб-сервера завершился ошибкой: nginx: unknown directive "uwsgi_pass"
проблема оказалась в том, что дефолтный веб-сервер в репозитории squeeze-а не содержит по дефолту модуль для работы с uwsgi.
Это изменено начиная с nginx версии 0.8. В репозитории 0.7.67 - так что все объяснимо.
Качаю исходники последнего стабильного релиза nginx:
Да, дефолтную версию nginx лучше удалить.
Альтернатива? Буду банален - nginx.
Решил описывать все камушки, каменюги , грабли и грабельки , на которые буду наступать в ходе освоения этого броузера.
Итак, первая "проблема":
На Debian 6 установил nginx из репозитория .
Настроил на взаимодействие с django проектом через uwsgi.
Первый запуск веб-сервера завершился ошибкой: nginx: unknown directive "uwsgi_pass"
проблема оказалась в том, что дефолтный веб-сервер в репозитории squeeze-а не содержит по дефолту модуль для работы с uwsgi.
Это изменено начиная с nginx версии 0.8. В репозитории 0.7.67 - так что все объяснимо.
Качаю исходники последнего стабильного релиза nginx:
cd /usr/src/nginx
wget http://nginx.org/download/nginx-1.1.9.tar.gz
tar xfz nginx-1.1.9.tar.gz
cd nginx-1.1.9
#подсмотрел рекомендуемые опции конфигурирования в инете :)
./configure --pid-path=/var/run/nginx.pid \
--conf-path=/etc/nginx/nginx.conf \
--sbin-path=/usr/local/sbin \
--user=www-data \
--group=www-data \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--with-http_stub_status_module \
--with-ipv6 \
--with-http_ssl_module \
--with-http_realip_module \
--with-sha1-asm \
--with-sha1=/usr/lib \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--with-http_geoip_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-http_addition_module \
--with-file-aio \
--without-mail_smtp_module
#модулей много заюзали, так что у вас configure может ругнуться на отсутствие необходимых
#для сборки библиотек..
#ставим все, что нужно
apt-get install libpcre3 libpcre3-dev openssl libssl-dev libgeoip-dev libgeoip1
#после этого конфигурируется без ошибок
make
make install
mkdir /var/tmp/nginx #ибо при конфигурировании мы попросили nginx писать времянки именно сюда)
chown www-data /var/tmp/nginx #вместо www-data подставьте нужного пользователя
Да, дефолтную версию nginx лучше удалить.
вторник, 20 марта 2012 г.
django: range - цикл в шаблоне
Встроенный в django шаблонный движок , как оказалось, не поддерживает циклы по диапазону значений.
Например , в шаблон передается некоторое число и необходимо организовать цикл от 0 до этого числа - 1
Средствами встроенных шаблонных тегов и фильтров сделать это , судя по всему , нельзя. Но есть простое решение : передавть в шаблон не число а значение, возвращаемое встроенной python-функцией range.
Например там, где было
надо сделать
после чего в шаблоне можно уже делать вот так:
Например , в шаблон передается некоторое число и необходимо организовать цикл от 0 до этого числа - 1
Средствами встроенных шаблонных тегов и фильтров сделать это , судя по всему , нельзя. Но есть простое решение : передавть в шаблон не число а значение, возвращаемое встроенной python-функцией range.
Например там, где было
... context['num'] = Somemodel.objects.count(), ...
надо сделать
... context['num'] = range(Somemodel.objects.count()), ...
после чего в шаблоне можно уже делать вот так:
...
{%for i in num%}
...
{%endfor%}
...
четверг, 23 февраля 2012 г.
django: Internal Server Error при debug = False
Сегодня напоролся на неприятный "баг" в django-flatpages.
Суть его в том, что при отключенном дебаге (settings.debug = False) возникает ошибка при попытке отобразить url с flatpage.
Включаешь дебаг - страницы отображаются . Отключаешь - видишь 500-тку. Мистика.
Оказалось, что для решения проблемы потребовалось разместить в templates/flatpages файл default.html , наследующий базовый шаблон. Ни один из моих url не использует этот дефолтный шаблон, но тем не менее он оказывается краеугольным камнем проекта.
Глупо да? Я тоже так думаю...
Суть его в том, что при отключенном дебаге (settings.debug = False) возникает ошибка при попытке отобразить url с flatpage.
Включаешь дебаг - страницы отображаются . Отключаешь - видишь 500-тку. Мистика.
Оказалось, что для решения проблемы потребовалось разместить в templates/flatpages файл default.html , наследующий базовый шаблон. Ни один из моих url не использует этот дефолтный шаблон, но тем не менее он оказывается краеугольным камнем проекта.
Глупо да? Я тоже так думаю...
вторник, 3 января 2012 г.
Отладка django+mod_wsgi: помощь при головной боли начинающего
Одной из первых проблем , с которыми сталкиваются начинающие django-разработчики при развертывании своих творений - это их отладка в продакшене. Например, такой вариант: Apache+mod_wsgi+django.
Вот в кратце список того, с чем пришлось столкнуться мне:
Предусловия:
1. В наличии имелся виртуальный сервер с Debian 5 Lenny , Apache2, python2.5 (из коробки) + доустановленный python 2.7.
2. Среди виртуальных хостов уже крутился один django-проект, использующий python2.5 и развернутый при помощи mod_python.
3. Доустановка нужного python 2.7 не доставила проблем, как и разработка и отладка с помощью встроенного в django веб-сервера. Когда настала пора деплоить проект на имеющийся apache, выбор пал на mod_wsgi.
4. Создан виртуальный хост и питоновский обработчик wsgi запросов от апача - все по мануалу, ошибиться было трудно.
Далее о многочисленных граблях, на которые пришлось наступить:
1. Установил mos_wsgi из репозитория - ничего не заработало.
Это потому что в репозитории lenny есть только модули , собранные для версии 2.5
Пришлось собирать mod_wsgi из исходников с нужной (2.7) версией python
2. Далее сглупил, собрав mod_wsgi без флага --enable-shared.
3. Потратил время, пытаясь запустить apache2 с виртуальными хостами, использующими разную версию python. Один - использует mod_python и сам интерпретатор версии 2.5. Другой (который пытаюсь развернуть) - только что собранный mod_wsgi для python 2.7. В такой конфигурации и без использования virtualenv так и не удалось заставить работать оба сайта. Причина оказалась не очень явная - mod_python всегда загружался первым и тянул за собой либы для 2.5 версии. И последующие ухищрения с настройками mod_wsgi и окружения не помогали. Решения было два: начать использовать virtualenv или пересобрать mod_python для версии 2.7 и запустить старый сайт с 2.7 версией python. Я выбрал второй вариант.
4. Долго пытался собрать mod_python версии 2.7.*, пока не понял, что бьюсь башкой о баг. Скачал версию 3.x.x , успешно собрал и установил , теперь уже не забывая про сборку именно шаред-библиотеки. После этого связку apache2+mod_wsgi можно было считать работающей.
5. Долго пытался отлаживать (путем print в стандартные потоки) причины 500-ток, пока не набрел на совет, как обернуть wsgi-приложение так, чтобы спроксировать дебаг-информацию в mod_wsgi. Вот какое решение (django.wsgi) мне помогло увидеть долгожданную дебаг-информацию в стиле django в окне броузера:
Предварительно надо установить paste:
6. После того, как появился нормальный дебаг в броузере первпя проблему, которую пришлось решить это Unable to Open Database File. Было ясно , что процессам апача не хватает прав на работу с файлом бд (речь идет о sqlite). Пермишены были добавлены, но ошибка осталась. Некоторое время ушло на понимание того, что надо дать еще права на директорию, в которой находится файл БД - такова особенность работы orm с данной СУБД.
7. после этого были подправлены некоторые директивы import по файлам проекта
8. статику тоже не сразу увидел (css, js) - не были настроены алиасы в виртуальном хосте. Вот, что было нужно добавить:
Вуаля, apache2+mod_wsgi-3.3.1+python2.7+django-1.3+sqlite успешно заработало.
Да , был забавный момент. В настройке WSGIScriptAlias зачем-то сдуру указал 30 потоков использовать и забыл об этом успешно. Долго не мог понять , почему моя vrs-ка стала загибаться. Чуть было не снес все , что переустановил. Вовремя заметил эту самонадеянную настройку и ограничился всего лишь 4 мя потоками.
Вот в кратце список того, с чем пришлось столкнуться мне:
Предусловия:
1. В наличии имелся виртуальный сервер с Debian 5 Lenny , Apache2, python2.5 (из коробки) + доустановленный python 2.7.
2. Среди виртуальных хостов уже крутился один django-проект, использующий python2.5 и развернутый при помощи mod_python.
3. Доустановка нужного python 2.7 не доставила проблем, как и разработка и отладка с помощью встроенного в django веб-сервера. Когда настала пора деплоить проект на имеющийся apache, выбор пал на mod_wsgi.
4. Создан виртуальный хост и питоновский обработчик wsgi запросов от апача - все по мануалу, ошибиться было трудно.
Далее о многочисленных граблях, на которые пришлось наступить:
1. Установил mos_wsgi из репозитория - ничего не заработало.
Это потому что в репозитории lenny есть только модули , собранные для версии 2.5
Пришлось собирать mod_wsgi из исходников с нужной (2.7) версией python
2. Далее сглупил, собрав mod_wsgi без флага --enable-shared.
3. Потратил время, пытаясь запустить apache2 с виртуальными хостами, использующими разную версию python. Один - использует mod_python и сам интерпретатор версии 2.5. Другой (который пытаюсь развернуть) - только что собранный mod_wsgi для python 2.7. В такой конфигурации и без использования virtualenv так и не удалось заставить работать оба сайта. Причина оказалась не очень явная - mod_python всегда загружался первым и тянул за собой либы для 2.5 версии. И последующие ухищрения с настройками mod_wsgi и окружения не помогали. Решения было два: начать использовать virtualenv или пересобрать mod_python для версии 2.7 и запустить старый сайт с 2.7 версией python. Я выбрал второй вариант.
4. Долго пытался собрать mod_python версии 2.7.*, пока не понял, что бьюсь башкой о баг. Скачал версию 3.x.x , успешно собрал и установил , теперь уже не забывая про сборку именно шаред-библиотеки. После этого связку apache2+mod_wsgi можно было считать работающей.
5. Долго пытался отлаживать (путем print в стандартные потоки) причины 500-ток, пока не набрел на совет, как обернуть wsgi-приложение так, чтобы спроксировать дебаг-информацию в mod_wsgi. Вот какое решение (django.wsgi) мне помогло увидеть долгожданную дебаг-информацию в стиле django в окне броузера:
import os
import sys
sys.stdout = sys.stderr
# Add the virtual Python environment site-packages directory to the path
import site
sys.path.insert(0,'/www/djangoprojects/')
sys.path.insert(0,'/www/djangoprojects/testproject/')
print sys.path
os.environ['DJANGO_SETTINGS_MODULE'] = 'yourapp.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
from django.conf import settings
# Debug middleware
if settings.DEBUG:
print >> sys.stderr, "Using Paste error middleware"
from paste.exceptions.errormiddleware import ErrorMiddleware
application = ErrorMiddleware(application, debug=True, show_exceptions_in_wsgi_errors=True)
print "here"
if settings.SESSION_FILE_PATH:
try:
os.makedirs(settings.SESSION_FILE_PATH)
except OSError:
pass
Предварительно надо установить paste:
sudo easy_install paste
6. После того, как появился нормальный дебаг в броузере первпя проблему, которую пришлось решить это Unable to Open Database File. Было ясно , что процессам апача не хватает прав на работу с файлом бд (речь идет о sqlite). Пермишены были добавлены, но ошибка осталась. Некоторое время ушло на понимание того, что надо дать еще права на директорию, в которой находится файл БД - такова особенность работы orm с данной СУБД.
7. после этого были подправлены некоторые директивы import по файлам проекта
8. статику тоже не сразу увидел (css, js) - не были настроены алиасы в виртуальном хосте. Вот, что было нужно добавить:
Alias /mediaurl /path/to/filesOrder allow,deny Allow from all
Вуаля, apache2+mod_wsgi-3.3.1+python2.7+django-1.3+sqlite успешно заработало.
Да , был забавный момент. В настройке WSGIScriptAlias зачем-то сдуру указал 30 потоков использовать и забыл об этом успешно. Долго не мог понять , почему моя vrs-ка стала загибаться. Чуть было не снес все , что переустановил. Вовремя заметил эту самонадеянную настройку и ограничился всего лишь 4 мя потоками.
среда, 28 декабря 2011 г.
Django: "Кто на сайте" ?
В одном из проектов понадобилось реализовать функцию "Кто на сайте". Средней продолжительности копания привели к модулю django-onlineiser.
$sudo easy install django-onlineuser
далее в settings.py:
#добавляем приложение в список используемых в проекте
INSTALLED_APPS += ('oblineuser')
#регистрируем его middleware в соответствующем списке
MIDDLEWARE_CLASSES += ('onlineuser.middleware.OnlineUserMiddleware')
в нужном html шаблоне подгружаем теги этого приложения и там же отображаем html-код этой приблуды
{% load onlineuser_tags %}
Кто здесь?
{%onlineinfos%}
У меня, чтобы заработало пришлось немного модифицировать код класса из middleware.py, обернув имеющийся там код в try except
class OnlineUserMiddleware:
def process_request(self, request):
try:
user = request.user
ip=request.META['REMOTE_ADDR']
if user.is_authenticated():
o, created = Online.objects.get_or_create(user=user)
o.session_key = ip
else:
o, created = Online.objects.get_or_create(ident=ip)
o.session_key = ip
if not created:
o.save()
except:
return
В результате видим простейшую статистику о гостях и онлайн юзерах.
С первого взгляда все ок и автору приложения в любом случае спасибо.
Но чуть позже стало понятно 2 факта (помимо бага описанного выше):
1. сразу после логаута пользователя счетчик пользователей не уменьшается, а счетик гостей не увеличивается
2. после логина счетчик гостей не уменьшается, хотя счетчик пользователей увеличивается
Не совсем релевантно получается.
Я допилил это приложение с помощью сигналов о логине и логауте:
#этот код я добавил в middleware.py рассматриваемого приложения, хотя можно и любое другое удобное место
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
@receiver(user_logged_in)
def count_logins(sender,request,user,**kwargs):
ip=request.META['REMOTE_ADDR']
g=Online.objects.get(session_key=ip, user=None)
if(g):
g.delete() #удаляем гостя , после того , как он стал залогиненным юзером
#создаем или обновляем запись в таблице приложения (этот код я скопипастил из имеющегося миддлваре-класса
o, created = Online.objects.get_or_create(user=user)
o.session_key = ip
if not created:
o.save()
@receiver(user_logged_out)
def count_logouts(sender,request,user,**kwargs):
o=Online.objects.get(user=user)
o.delete() #сразу при логауте удаляем запись из таблицы
Если в ближайшее время не придумаю как более красиво это все дело улучшить, отпишу автору или посто форкну это приложение )
четверг, 1 декабря 2011 г.
Django: Добавляем свои собственные проверки объектов в админку
Если понадобилось дополнить стандарные проверки, которые делает Django при создании, редактировании, удалении объектов через панель администратора, то существует несколько извращенных способов.
Опишу самый простой, наглядный и незатратный.
Начиная с версии 1.2 в Django позволяет добавлять в модель метод clean, в котором и предлагается реализовывать логику нужных вам проверок.
Например у вас есть таблица "Матч" , в полях которой есть две ссылки (ForeignKey) на таблицу "Команда". То есть играют две команды ) Сама с собой команда, понятно, играть не может. По крайней мере в тех командных видах спорта , о которых доводилось слышать )
Код проверки будет примерно прост (добавить метод в класс модели "Матч"):
def clean(self):
from django.core.exceptions import ValidationError
if(self.team1.id == self.team2.id):
raise ValidationError('Команда не может играть сама c собой.')
В результате , при попытке сохранения матча где команда намеревается рубиться сама с собой , админ увидит красненький баннер с соответствующим сообщением.
p.s. сейчас в голову пришла мыслишка: будет ли вызываться этот метод, при сохранении объекта не через админку..хм.. надо будет матчасть почитать или выяснить эмпирически.
Если кто уже в курсе - буду признателен за ответ. Хотя кому это я, читателей пока у меня судя по всему нет )))))
Подписаться на:
Сообщения (Atom)