Публикации с меткой «mysql»

Блог django на хабрахабре

Django и особенности использования транзакций в MySQL

Наверное всем известно, что Django является одним из самых популярных фреймворков для web-разработки на python-е. И даже если в основе web-проекта лежит сторонний код, то зачастую при разработке используют отдельные части этого фреймворка — например ORM. В данной статье я хотел бы рассказать об особенностях использования Django ORM при работе с базой данных MySQL, а именно про транзакции и подводные камни, связанные с ними. Так, например, если в какой-то момент вы осознаёте, что вместо ожидаемых данных, возвращается совершенно другой результат, то возможно, данная статья поможет разобраться что к чему.
Читать дальше →

Блог python на хабрахабре

Python / MySQLdb vs UTF-8

Традиционная проблема базы и кодировок.

При подключении обычным способом к MySQL через MySQLdb во время записи строк в кодировке utf-8 имеем неприятный момент: UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-5: ordinal not in range(256) Как не игрался с кодировками — либо это исключение, либо крякозябры в базе. Кроме того, даже чтение записей выдает не то, что ожидалось увидеть…

Блог python на хабрахабре

Язык программирования Python / FTP сервер с авторизацией через базу данных



Существует множество готовых FTP серверов для разворачивании у себя на сервере. Но сложилось так что, на сервере уже работает FTP и нужно поднять FTP сервер на альтернативном порту. А также раздать пользователям доступ только к своим папкам с файлами. Решил поинтересоваться, а что можно сделать средствами Python. Поиск быстро выдал библиотеку pyFTPd.

Блог django на хабрахабре

Django Framework / GROUP_CONCAT для Django ORM


Агрегатные функции в Django ORM — крутые. Это обстоятельство послужило поводом добавить еще одну =)

Далее речь пойдет о mysql-специфичной функции GROUP_CONCAT и волшебных розовых пони, как на картинке django-trunk.

CAN HAZ SOM BLOG?

Маескулевцы не сдали бы ЕГЭ

Потому что с геометрией у них плохо :) Наваял тут скриптец для гуглокарт, который по нажатию на точку на карте определяет на какую страну ткнули. Юзал стандартные шейпы мировой карты. Мускуль почему-то считает что рашка есть, например, в Испании, а София принадлежит аж трём странам — Украине, Болгарии и Словакии (или Словении). Вообще, парадоксальная ситуация, когда точка на карте может принадлежать больше чем одной стране в принципе объяснима, но такие загибы уж черезчур.

Поставил постгри и PostGIS, загнал те же шейпы и тем же скриптом — всё великолепно стало определяться. И София кому надо принадлежит, и Испания не входит в состав эрефии.

Так что, если нужна более-менее точная геометрия, то mysql еще совсем не готов.

Справедливости ради, надо сказать, что для постгри это всё на хранимках и дататайпах организовано как я понял, а в мускуле это "искаропки". И есть вроде бы сторонние хранимки для мускуля, которые исправляют ситуацию.

ЗЫ. Поросёнок Пётр™ совсем устремился в атаку.

ЗЗЫ. Геоджанга это просто праздник какой-то. +100 в карму авторам :).

Изучаем Django

Система развертывания (deploy system)

.clip { display: block; background: #EEE; border: 1px dashed #999; padding: 1em 1em 0 1em; }

Как я и обещал в предыдущей серии, посвящаю этот пост нашей системе развертывания.

Система самописная, достаточно тесно связана с процессом разработки и реализована при помощи sh-скрипта.

Общая схема

На рисунке приведена немного сумбурная схема процесса развертывания.

Разработка ведется с использованием SVN установленным на локальном сервере, там же расположен и локальный сервер MySQL. MySQL используется всеми при разработке, структура создается через initdb. Начальные данные в обязательном порядке (скоро узнаете почему) сохраняются либо в fixtures, либо в init.sql, а в случае прав пользователей создается команда manage.py.

После каждого коммита автоматически запускается скрипт развертывания на DEV версию проекта. При этом исходный код на сервере обновляется (или загружается если проекта не существует), а структура базы обновляется при помощи замечательного mysqldiff. На схеме этот процесс помечен цифрой 1.

DEV версия проекта — инструмент разработчиков, расположен на хостинге проекта, но закрыт для просмотра не из локальной сети. Обновляется после каждой загрузки кода в репозиторий.

Используется редко, в основном для проверки ошибок возникающих из-за разных версий ПО и ОС на компьютерах разработчиков и хостинге.

Когда проект готов для тестирования, менеджер проекта запускает (по ssh;) развертывание на TEST он же помечен цифрой 2 на схеме. Структура база данных переносится из DEV версии.

TEST версия проекта — инструмент тестировщиков, как и DEV расположен на хостинге проекта, но закрыт для просмотра не из локальной сети. Обновляется по запросу, когда система готова к тестированию.

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

На этот раз файлы проекта не обновляются из репозитория, а копируются из DEV версии. Старая версия проекта удаляется. В сложной ситуации это дает больше свободы, и базу данных и файлы проекта мы можем подкорректировать на хостинге и эти изменения попадут в тестирование.

Процесс деплоя на TEST выполняется итеративно, пока не будут исправлены все обнаруженные ошибки. И тогда наступает час X, менеджер проекта достает большую красную кнопку и запускает развертывание на PROD версию.

PROD версия проекта — инструмент пользователей. Используется интернет пользователями по назначению. (например для связи бизнеса и СМИ).

Обновляется по запросу, после окончания тестирования.

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

Расскажу об одном интересном моменте, почему при деплое не теряются пользовательские данные. Дело в том, что mysqldiff генерирует ALTER срипт, который изменяет лишь структуру БД, но не трогает сами данные. Файлы загруженные пользователями хранятся в отдельном месте и подключаются в структуру проекта с помощью символической ссылки. Таким образом мы имеем три независимых версии со своими данными в базе и загруженными файлами.

Конфигурация системы

Система планировалась более-менее универсальной, поэтому у каждого проекта есть опции развертывания, которые должны храниться в файле deploy/params.sh. Основные параметры:

  • Параметры SVN репозитория, для скачивания и обновления исходного кода.
  • Параметры MySQL сервера, который используется для переноса изменений структуры на DEV.
  • Имя конечного конфигурационного файла, который формируется из шаблона для каждой версии проекта.
  • Путь к media и загружаемым файлам пользователя.
  • Базовые порты FCGI и SPHINX.
  • Команда выполняемая сразу после деплоя (обычно команда инициализации прав пользователей).
Параметры представлены как переменные и добавляются с помощью включения скрипта.

MySQL

С базой при деплое все достаточно просто, если её не существует, скрипт запускает создание базы manage.py initdb, Django загружает fixtures, скрипт запускает init.sql и в конце выполняет прописанную в конфиге команду. Огромное разнообразие методов начальной загрузки данных удовлетворяет любые даже самые сложные случаи.

Например, в свое время мы столкнулись со сложностью распределения прав пользователей по группам. На уровне fixtures или init.sql ну никак не получалось этого сделать, из-за того что на разных версиях проекта, созданные initdb права, имеют разные id. В итоге и появилась команда выполняемая в конце развертывания, которая используя стандартные методы Django, формирует необходимые группы пользоватей и распределяет права доступа.

Все эти сложности с начальными данными очень помогают в процессе разработки и при первом деплое на продакшн. Если что-то пошло не так, база сбрасывается и автоматически наполняется нужными данными. Очень удобно.

Если база данных уже создана, то при развертывании переносится только структура с помощью mysqldiff. Этот скрипт делает экспорт структуры двух баз данных (откуда и куда переносим), сравнивает эти данные и формирует sql скрипт для обновления целевой базы. Скрипт уже стандартными средствами СУБД применяется к базе. Причем при деплое на PROD, скрипт просматривается вручную, дабы в случае сбоя не удалить пользовательские данные.

Конфигурационные файлы

Одна из моих любимых функций нашей системы — генерация конфигурационных файлов.

Конфиг разработчиков хранится в отдельном файле base_settings.py а в стандартном settings.py всего одна строчка включения базовых настроек from base_settings.py import *.

Для настроек применяемых на хостинге создается специальный шаблон настроек template_settings.py в котором переопределяются нужные настройки из base_settings.py, причем следуя принципу DRY шаблонный файл всего один для всех трех версий системы.

Поведение специфичное для конкретной версии (имена баз данных, например, у всех разные) поддерживается макро-язык суть которого в замене конструкции {имя версии: значение} на значение. Допустим строка

DATABASE_NAME={dev:eshtab_dev}{test:eshtab_test}{prod:eshtab}
при развертывании на TEST будет исправлена на DATABASE_NAME = eshtab_test.

Но с другой стороны мы уже указали имя базы данных в params.sh, воскликнет внимательный читатель. Для решения этой проблемы активны специальные подстановки, вот примерный их список:

{instance}
DEV, TEST или PROD — версия системы.
{dbname}
имя базы данных.
{sitepath}
путь к файлам проекта.
{domain}
базовый адрес версии проектам (например dev.eshtab.ru).
{fcgi_port}
FCGI порт, используется как Django так и NGINX.
{sphinx_port}
порт поискового движка, используемого на наших проектах.
{media_path}
путь к статическим файлам.

Подстановки изумительны с точки зрения DRY, они используются как в Django так и в конфигурационных файлах SPHINX, NGINX, так и в скриптах запуска.

Макро-замены и подстановки осуществляются потоковым текстовым редактором sed. После замен settings.py заменяется шаблоном.

SPHINX, NGINX

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

Плюс, благодаря заменам и подстановке, на все версии системы по одному файлу конфигурации. Если их было бы по одному на каждую, правки доставляли некоторые неудобства. Вот небольшая часть конфигурационного файла веб-сервера:

{dev:#}{test:#}    server {
{dev:#}{test:#}        listen       80;
{dev:#}{test:#}        server_name .{domain};
{dev:#}{test:#}        rewrite ^/(.*) http://www.{domain}/$1 permanent;
{dev:#}{test:#}    
}

Как вы наверно догадались на DEV и TEST эти строки будут закомментированы, а на PROD веб-сервер будет переадресовывать запросы с domain на www.domain из эстетических соображений.

На правах заключения

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

Lazy Crazy Coder's blog

How to create a global lock using MySQL

When you writing a distributed application or webservice, sometimes you need to synchronize processes on different machines. For example, you may need to run some cron job once on a random machine.

If you are using MySQL, than you can ise it's GET_LOCK function, to accomplish this task. I wrote this helper to create global lock in python, using with statement:

import contextlib
@contextlib.contextmanager
@write_session
def global_lock(name, timeout, session):
    result = session.execute('SELECT GET_LOCK(%s, %s)', (name, timeout)).fetchall()
    result = len(result) == 1 and result[0][0]
    try:
        yield result and True or False
    finally:
        if result:
            session.execute('DO RELEASE_LOCK(%s)', (name, ))

Here write_session is decorator, which passes a session argument to a function. Here I use sqlalchemy's session, but you could use MySQLdb's connection or something like that.

And here is one of usecases for function:

def cron():
    with global_lock('myapp.cron_lock', 0) as acquired:
        if acquired:
            do_something_significant()
        else:
            exit_without_doing_any_job()

That's it. But make sure, to use unique name for the lock, because you may get in trouble if some other application uses same name.

Lazy Crazy Coder's blog

How to create a global lock using MySQL

When you writing a distributed application or webservice, sometimes you need to synchronize processes on different machines. For example, you may need to run some cron job once on a random machine.

If you are using MySQL, than you can ise it's GET_LOCK function, to accomplish this task. I wrote this helper to create global lock in python, using with statement:

import contextlib
@contextlib.contextmanager
@write_session
def global_lock(name, timeout, session):
    result = session.execute('SELECT GET_LOCK(%s, %s)', (name, timeout)).fetchall()
    result = len(result) == 1 and result[0][0]
    try:
        yield result and True or False
    finally:
        if result:
            session.execute('DO RELEASE_LOCK(%s)', (name, ))

Here write_session is decorator, which passes a session argument to a function. Here I use sqlalchemy's session, but you could use MySQLdb's connection or something like that.

And here is one of usecases for function:

def cron():
    with global_lock('myapp.cron_lock', 0) as acquired:
        if acquired:
            do_something_significant()
        else:
            exit_without_doing_any_job()

That's it. But make sure, to use unique name for the lock, because you may get in trouble if some other application uses same name.

Lazy Crazy Coder's blog

Django External Schema Evolution Branch

Django External Schema Evolution Branch is a django module, which allows to evolve from one database scheme to another.

DESEB automatically builds all necessary ALTERs, INSERTs and UPDATEs. Currently it works with mysql 5.0 and postgresql 8.2. Work with sqllite3 is not guaranted.

Изучаем Django

Установка и настройка

Для создания Django приложения понадобятся:
  • Python
  • Python-Imaging для работы с изображениями
  • Subversion (для получения исходного кода Django)
  • MySQL и MySQLdb для связи БД с Python
  • Текстовый редактор
  • Django
Рассказывать буду кратко, применительно к Linux и Windows. Если возникнут какие-либо проблемы или вопросы спрашивайте, отвечу.

Linux

Здесь все просто необходимые программы есть в репозитарии, приведу пример для Ubuntu:
sudo apt-get install python
sudo apt-get install subversion
sudo apt-get install mysql-server
sudo apt-get install python-mysqldb
sudo apt-get install python-imaging
Текстовый редактор подойдет любой: kate — если вы используете KDE, gedit — если Gnome или можете попробовать Komodo Edit.

Windows

Ссылки на дистрибутивы:
  • Python
  • python-imaging
  • Subversion: консольный клиент либо Tortoise — удобная графическая оболочка.
  • MySQL, MySQLdb
  • Текстовый редактор подойдет любой, но лучше с подсветкой синтаксиса, например, Komodo Edit, прекрасно справляется как с Python кодом так и с Django шаблонами.

Django

Для получения исходных кодов Django необходимо выполнить команду: svn co http://code.djangoproject.com/svn/django/trunk/ Либо, если вы установили Tortoise, выберите в контекстном меню (правая кнопка в проводнике) «Svn checkout» и введите адрес http://code.djangoproject.com/svn/django/trunk/. Затем запустите консоль и выполните команду: python setup.py install

Создание проекта

Django проект — содержит в себе настройки доступа к бд, настройки Django и исходный код приложений. Перейдите в директорию, где вы собираетесь размещать ваш исходный код и выполните команду: django-admin.py startproject coblogs Эта команда создаст директорию coblogs для нашего приложения и начальные настройки. Необходимо создать базу данных для нашего приложения (убедитесь что MySQL сервер запущен):
$mysql -u root
mysql> CREATE DATABASE coblog CHARACTER SET UTF8;
Query OK, 1 row affected (0.00 sec)
и настроить доступ к ней, откройте файл coblogs/setting.py и измените следующие настройки:
DATABASE_ENGINE = 'mysql'      # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'coblog'       # Or path to database file if using sqlite3.
DATABASE_USER = 'root'         # Not used with sqlite3.
DATABASE_PASSWORD = ''         # Not used with sqlite3.
DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.

LANGUAGE_CODE = 'ru-ru'
Позволим Django записать свои данные в только что созданную базу:
coblog$ python manage.py syncdb
В ходе этого процесса вас спросят имя для аккаунта администратора и пароль, запомните введенные данные они нам еще понадобятся. Пример правильного вывода команды:
python manage.py syncdb
Creating table auth_message
Creating table auth_group
Creating table auth_user
Creating table auth_permission
Creating table django_content_type
Creating table django_session
Creating table django_site

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'root'): 
E-mail address: a@a.ru
Password: 
Password (again): 
Superuser created successfully.
Installing index for auth.Message model
Installing index for auth.Permission model
Если то что вы увидели сильно отличается от приведенного листинга, скорее всего имеет место ошибка доступа к БД (не запущен сервер, неверные имя пользователя и пароль, ошибка установки драйвера). Проверьте настройки и попробуйте еще раз.

Метки

.net .NET C# .sort 1.2 2009 2010 404 error admin ajax amazon analytics and apache api archlinux asp.net async asynchronous autocomplete bash blender blog blogengine blogs book bootstrap bot bpython buildout byteflow bzr C c plus plus C++ cache cbv Chaco checkio chrome ci ckeditor class based views clojure closure cms cms с удобной админкой code coding style collectd COM comet competition conference ConfigParser contest Context continuous integration CouchDB coverage CppCMS cpyext cpython crud csrf CSS ctypes curl custom model fields cx_freeze cython database db dbm dbqueries debian debug debugging decorator decorators deploy deployment descriptor design dev devconf developers development diveintopython Django django 1.2 django 1.3 django advent django framework django template django trunk django weblog django-admin-tools django-cms django-compressor django-hosts django-piston django-registration django-sphinx django.admin djangoadvent djangocms djangodash doc documentation drupal e-legion eclipse EGit emacs encoding Enthought epoll erlang event exception ExtJS fabric facebook fastcgi finaloption fixtures fonts forms formset fp framework freebsd freeswitch fs2web ftp fun funcparserlib functional gae gamin gandi generic views gettext gevent gil git github gitosis Google Google App Engine google picasa Google Translate google wave Google Web Toolkit grab grablab greenlet gtd gui haskell hg hgshelve highlighter host hosting how-to howto html html5lib Hudson humor i18n icfpc ide idiomatic image-scripting improvements Internet interpreter ipython ironpython izmenimsya.ru jabber java javascript jenkins jetbrains JIT job jquery json jstree jython kde kiev kiyv kyivpy l10n ldap library libs Life Links linux Linux & Unix LLVM logging logs lxml Mac OS X magic mail markdown Matplotlib Mayavi maybe mediavirus meetup memcache Memcached memory messages metaclass middleware migration mikrotik mkd model models mod_python mod_wsgi mongodb monitoring mptt musicmans.ru musicx mvc my-projects mysql netCDF networkx newforms newforms-admin news nginx Nhibernate nix nose NoSQL numpy oop open source OpenID openoffice opster optimization oracle orm os pagination parsing path patterns pdf PDF-принтер PEP PEP8 performance performance optimization perl personality photo php picture-driven computing PIL pinax pingback pip plasma plone plugin plugins postgresql programming progress bar psycopg2 py2exe pybb pybbm pycamp pycharm pycon pycow pycurl pydev pygtk pylons PyNGL pypy pyqt PyQt4 pyrad pyramid PySide Python Python 2.5 python 2.7 python 3 python c api python speed python-mssql python3 pywinauto Qt Qt4 queue rabbitmq radius raw sql re redis redsolution redsolution cms regexp regular expressions release repoze.bfg RequestContext reusable apps robokassa rss ru ruby ruby-on-rails sample satchmo scalability SciPy scraping screencast search selenium self.error seo server setattr settings setuptools shell sikuli sms snippet socket.io software sorting south sphinx spider sql sqlalchemy sqlite ssh startup step-by-step subdomain subversion svn SyntaxHighlighter system tags tdd tddspry teh drama template templates templatetags test testing thinkpad threading threads tips tips and tricks tools tornadio tornado tornado server tricks tutorial tweepy twisted twitter typography uapycon Ubuntu ucsvlog uml Uncategorized unicode unit test unit testing UnitTest Unladen Swallow upload urllib urls utf-8 uwsgi validation vcs versioning video vim virtualenv Visual Studio vkontakte voip wave web web-devel web-services web-разработка webdev webfaction webkit webpy websockets webtest widget widgets Win API windows Wirbel work wrapper wsgi wxPython wxWidgets wysiwyg xapian xml xmonad xmpp xpath yandex youtube zip zomg zope [cdata[cbv]] [cdata[ci]] [cdata[class based views]] [cdata[continuous integration]] [cdata[django framework]] [cdata[django-sphinx]] [cdata[django]] [cdata[nginx]] [cdata[python]] [cdata[virtualenv]] [cdata[программирование]] автоматизация администрирование администрирование django админка алгоритмы архитектура атрибуты базы данных Без рубрики безопасность библиотеки блоге бот веб-разработка видео Визуализация данных вконтакте Все записи гвидо ван россум граббер графика графы декоратор декораторы дескриптор дескрипторы документация заметки игра жизнь идея интересное киев Клиентам книги конференция личное математика метаклассы модели модули монады морфология мысли невозможное новости о облачные вычисления обо мне Обработка данных оптимизация оптимизация кода Основная лента основы парсинг парсинг сайтов перевод песочница Питон поебень поиск правила кодирования программирование Проектирование производительность работа рабочее размышлизмы Разное разработка разработка приложений разработки регулярные выражения сайт событие события ссылки статьи тестирование тесты Тюмень убунтариум фигня философия формы форум Хабрахабр хакинг хостинг шаблоны шаблоны проектирования эксперимент Эксперименты юмор я пиарюсь Яндекс