Django
Установка Django, PostgreSQL, Nginx на Debian сервере с нуля
Оригинал статьи размещен по адресу http://www.mindinmotion.ru/content/207.html
Решил снова попробовать Django. Некоторое время назад я перевел все сайты что начинал делать на Django на Drupal, либо на самописные решения, созданные с помощью Zend Framework. Тогда я руководствовался тем что надо хорошо знать какой один язык и забросил Python и Django. Сейчас все же решил снова вернутся к Django по нескольким причинам, во первых все таки многие вещи в Django делаются быстрее, ну например те же формы, даже используя Zend Form кода все равно в разы получается больше, особенно если валидаторы присобачивать, фильтры, кастомизировать как будет форма отображаться.
Ну вот как пример, кусок из одной партнерки которую я писал:
$emailValidator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS, true); $email = new Zend_Form_Element_Text('email'); $email->setLabel('Email') ->setRequired(true) ->addFilter('StripTags') ->addFilter('StringTrim') ->addValidator($emailValidator) ->addErrorMessage('Ошибка: Email неправильный.'); 'ViewHelper','Description', 'Errors', ));
В общем ладно, перехожу к описанию установки Django, в качестве базы решил использовать PostgreSQL, лично для меня пофиг какая база PostgreSQL или MySQL, решил использовать PostgreSQL потому что сами разработчики Django когда разрабатывали свой фреймворк, затачивали его под Postgres.
# aptitude install postgresql
Правим файл /etc/postgresql/8.4/main/postgresql.conf (здесь и дальше по тексту заменяем 8.4 на свою версию), меняем
# listen_addresses = 'localhost'
на
listen_addresses = 'localhost, 192.168.1.10'
В моем случае я прописываю внутренний айпишник сервера - 192.168.1.10
Дальше правим файл /etc/postgresql/8.4/main/pg_hba.conf, находим строку # IPv4 local connections:
добавляем
host all all 192.168.1.1/24 md5
перезапускаем
# /etc/init.d/postgresql-8.4 restart Restarting PostgreSQL 8.4 database server: main.
Если все сделали правильно Postgres начнет ждать подключений на нужном айпишнике.
# netstat -tanp |grep postgre tcp 0 0 192.168.1.10:5432 0.0.0.0:* LISTEN 23104/postgres tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 23104/postgres tcp6 0 0 ::1:5432 :::* LISTEN 23104/postgres
Создаем нового юзера (в моем примере newuser) и зададим ему пароль qwerty
# su postgres postgres@srv01:/etc/postgresql/8.4/main$ createuser newuser Shall the new role be a superuser? (y/n) n Shall the new role be allowed to create databases? (y/n) n Shall the new role be allowed to create more new roles? (y/n) n $ psql template1 psql (8.4.1) Type "help" for help. template1=# alter user newuser password 'qwerty'; ALTER ROLE
Заодно сменим пароль для пользователя postgres
template1=# ALTER ROLE postgres WITH ENCRYPTED PASSWORD 'my-super-secret-password'; ALTER ROLE postgres=# \q
Создаем базу для пользователя newuser, на запрос пароля вводим пароль, который мы установили для пользователя postgres (my-super-secret-password)
$ createdb websitedb --owner=newuser -hlocalhost Password:
Теперь пробуем подключиться с клиентской машины
$ psql -Unewuser -W -hsrv01.lan Password for user newuser: psql (8.4.1) SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) Type "help" for help. newuser=>
С базой покончено, можно настраивать сайт
# mkdir /var/www/yourwebsite # chown yourusername:yourusername /var/www/yourwebsite
Поясню этот шаг, у меня сервак используется для решения задач по разработке, так что я не ставлю целью сделать подобные проекты секьюрными и решаю вопросы по настройке сайтов исходя из того как мне удобно. Я монтирую директории по ssh и поэтому я меняю вдалельца каталогов на юзера yourusername - это тот юзер, которым я подключаюсь/монтирую по ssh этот проект.
Я использую Django из SVN, то есть самую последнюю версию, и я решил держать ее в той же директории, где будет находиться сайт. Тут есть одна особенность - сервер работает под юзером www-data, так что для директории с django я сменю owner на www-data, и туда же счекаютю последнюю версию Django, перед этим став юзером www-data.
srv01:/var/www/yourwebsite# mkdir django-trunk srv01:/var/www/yourwebsite# chown www-data:www-data django-trunk/ srv01:/var/www/yourwebsite# su www-data srv01:~/yourwebsite$ cd django-trunk/ srv01:~/yourwebsite/django-trunk$ $ svn co http://code.djangoproject.com/svn/django/trunk/ . A LICENSE A django A django/test A django/test/simple.py A django/test/client.py A django/test/testcases.py ------------------- >8 вырезано ----------------------------- A examples/hello/urls.py A examples/views.py A examples/__init__.py A examples/settings.py A examples/urls.py A setup.cfg U . Checked out revision 11793. srv01:~/yourwebsite/django-trunk$ exit srv01:/var/www/yourwebsite#
Теперь нам надо узнать где находятся site-packages, для этого в консоли (в bash консоли, а не консоли python) надо набрать команду, приведеннуную ниже по тексту, в результате выполнения которой узнаем путь к site-packages.
# python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" /usr/lib/python2.5/site-packages
В процессе установки и написания этой статьи я решил что все таки лучше будет хранить последнюю версию Django в директории /var/www, чтобы каждый раз для каждого нового сайта не прописывать пути и каждый раз не апдейтить одну и ту же версию Django для разных сайтов.
# mv /var/www/yourwebsite/django-trunk /var/www
Далее необходимо сделать так чтобы Python мог загружать код Django, для этого необхоимо сделать symlink. После чего еще один symlink для того чтобы можно было запускать django-admin.py из любой директории.
# ln -s `pwd`/django-trunk/django /usr/lib/python2.5/site-packages/django
Для запуска Django как FastCGI server понадобится flup, который можно установить из пакетов.
# aptitude install python-flup
Создаем новый проект
$ django-admin.py startproject yourproject boris@srv01:/var/www/yourwebsite$ ls -lha total 12K drwxr-xr-x 3 boris boris 4.0K Dec 4 13:55 . drwxrwxrwx 60 www-data www-data 4.0K Dec 4 00:58 .. drwxr-xr-x 2 boris boris 4.0K Dec 4 13:55 yourproject boris@srv01:/var/www/yourwebsite$ ls -lha yourproject/ total 20K drwxr-xr-x 2 boris boris 4.0K Dec 4 13:55 . drwxr-xr-x 3 boris boris 4.0K Dec 4 13:55 .. -rw-r--r-- 1 boris boris 0 Dec 4 13:55 __init__.py -rwxr-xr-x 1 boris boris 546 Dec 4 13:55 manage.py -rw-r--r-- 1 boris boris 2.8K Dec 4 13:55 settings.py -rw-r--r-- 1 boris boris 550 Dec 4 13:55 urls.py
Проект создан, теперь можно запускать FastCGI сервер и настраивать Nginx.
boris@srv01:/var/www/yourwebsite/yourproject$ ./manage.py runfcgi method=threaded host=127.0.0.1 port=3033
Теперь создаем конфиг для nginx /etc/nginx/sites-available/yourwebsite (если не установлен, то устанавливаем командой sudo aptitude install nginx). Ниже содержимое этого файла:
upstream djangoserv { server 127.0.0.1:3033; } server { listen 80; server_name yourwebsite; root /var/www/yourwebsite/yourproject; access_log /var/www/ /logs/access.log; error_log /var/www/yourwebsite/logs/error.log; location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov) { access_log off; expires 30d; } location / { fastcgi_pass 127.0.0.1:3033; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param QUERY_STRING $query_string; fastcgi_param SERVER_NAME $server_name; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_pass_header Authorization; fastcgi_intercept_errors off; } }
После чего делаем symlink и включаем конфиг для нового виртуал хоста, создаем папку с логами и выставляем ей нужного владельца (www-data), после чего перезагружаем nginx.
srv01:/etc/nginx/sites-available# ln -s /etc/nginx/sites-available/yourwebsite /etc/nginx/sites-enabled/yourwebsite srv01:/etc/nginx/sites-available# mkdir /var/www/yourwebsite/logs srv01:/etc/nginx/sites-available# chown www-data:www-data /var/www/yourwebsite/logs # /etc/init.d/nginx reload Reloading nginx configuration: the configuration file /etc/nginx/nginx.conf syntax is ok configuration file /etc/nginx/nginx.conf test is successful nginx.
Если все сделали правильно теперь можно зайти по адресу http://yourwebsite и увидеть там дефолтную страницу Django с надписью It worked!
Django vs PHP
Примерно год назад я купил один домен и решил сделать подобие каталога на нем и так еще несколько сервисов по мелочи. В феврале я устроился работать веб-программером и забил на все это, потом время от времени я то возвращался к этому "проекту", то опять забрасывал его.
Я поискал несколько уже готовых скриптов для создания каталогов, в том числе и платных и взломанных, все было не тем что мне нужно было. Мне хотелось такой же каталог как Яндекс.Каталог или что-то подобное. Для хранения в базе данных древовидной структуры каталога я взял идею из этой презентации. В общем я написал класс для работы с таким каталогом. Потом меня это быстро все достало, мало того что надо было написать только этот класс, надо было еще написать админку. Кроме всего этого каталог был лишь частью того что мне хотелось создать на этом сайте.
Решил попробовать Drupal, там уже вроде было все что мне надо, в том числе и каталог, завязанный на taxonomy. Не помню чем, но он меня не устроил, хотя я и переписал его под себя как хотелось.
После того как я недавно решил что пора завязывать с раздолбайством, сел за написание всего, что хотелось на Django. Большую часть времени (несколько часов) заняло проектирование базы данных, дело в том что планируется достаточно много данных и если криво все спроектировать все рано или поздно начнет тормозить. Под сам каталог таблица получилась такая:
CREATE TABLE `directory_russia` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) NOT NULL, `path_string` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, `depth` int(11) NOT NULL, `region_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `directory_russia_region_id` (`region_id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
models.py в Django
class Russia(models.Model): parent_id = models.IntegerField() path_string = models.CharField(maxlength=255) name = models.CharField(maxlength=255) depth = models.IntegerField() region = models.ForeignKey(Region) def __unicode__(self): return self.name class Admin: pass
в views.py я написал только одну фукнцию которая строит путь от корня каталога, до текущего раздела:
def build_node_path(path): node_path = [] for node_id in path.rsplit('/'): node_object = Russia.objects.get(pk=node_id) node_path.append(<a href='/cat/' + str(node_object.id) + '/>' + node_object.name + '</a>') return " > ".join(node_path)
в итоге получается путь типа "Раздел-1 > подраздел-1 > подраздел-2"
сами данные для каталога хранятся в другой таблице
class Org(models.Model): directory = models.ManyToManyField(Russia) name = models.CharField(maxlength=255) description = models.TextField() directory_order = models.IntegerField(default=2) updated = models.DateTimeField(auto_now=True) def __unicode__(self): return self.name class Admin: pass
я немного изменил способ хранения, и путь храню примерно так 2/3/4 (то есть в начале и в конце нет /, в отличии примера с talks.php.net). В итоге по функциональности получается каталог точно такой же как у Яндекса, пока я застрял на постраничном выводе, он работает но не так как бы хотелось :)
Поле ManyToManyField позволяет хранить в разных разделах один и тот же элемент, примерно так же как если в яндекс каталоге зайти в Hi-tech там будут все элементы из всех подразделов.
ps: полезная настройка в settings.py которая устанавливает что все MySQL таблицы по умолчанию будут InnoDB
DATABASE_OPTIONS = {"init_command": "SET storage_engine=INNODB",}
если это не указать, то таблицы будут MyISAM и ForeignKeys создаваться не будут.
Установка Django под Windows
|
В продолжение предыдущего поста об установке Django на виртуальном хостинге сегодня хочу описать как установить django в операционной системе Windows.
Для начала необходимо скачать и установить:
Я ставил django из SVN (самую последнюю версию), для того чтобы ее скачать необходимо выполнить следующее: |
|
| В появившемся окне вводим URL: http://code.djangoproject.com/svn/django/trunk/ жмем ОК, дистрибутив начинает скачиваться |
|
|
Если все успешно скачается, появится надпись Updated X:\folder Completed At revision 6710 (число будет другим) Устанавливаем Django:
Теперь необходимо поменять переменные окружения, чтобы можно было вводить django-admin.py, а не полный путь к нему (типа C:\python25\somefolder\django-admin.py). |
|
|
После чего перезагружаемся.
Дальнейшая установка рассматривается в этом видео. |
Использование sqlite и Django
Создание каждой новой базы данных для нового веб-сайта на виртуальном хостинге довольно таки не дешевое занятие. Раньше при использовании Django я каждый раз заводил новую PosgreSQL базу, недавно зашел посмотрел во сколько мне это обходится, оказалось 841 рубль ![]()
В связи с тем что мои сайты потребляют очень мало трафика использовать полноценные базы данных смысла просто нет. Судя по информации на wiki sqlite использование этой базы данных оправдано для сайтов с посещаемостью до 10000 хитов в сутки.
Как установить Django на виртуальном хостинге
В последнее время много внимания уделяется различным веб-фреймворкам, в особенности Ruby on Rails, при этом незаслуженно многие забывают о существовании достаточно мощного средства для создания веб-приложений - Django. Среди веб-сайтов, которые используют Django - The Washington Post, Yandex и многие другие. На конференции Российские интернет технологии 2007 в своем выступлении сотрудники Яндекса рассказали о тестировании различных веб-фреймворков, по результатам тесВ последнее время много внимания уделяется различным веб-фреймворкам, в особенности Ruby on Rails, при этом незаслуженно многие забывают о существовании достаточно мощного средства для создания веб-приложений - Django. Среди веб-сайтов, которые используют Django - The Washington Post, Yandex и многие другие. На конференции Российские интернет технологии 2007 в своем выступлении сотрудники Яндекса рассказали о тестировании различных веб-фреймворков, по результатам тестирования наибольшую производительность показал Django.
Установка Django производилась на хостинге компании "Хостинговые телесистемы", это один из немногих хостингов, который поддерживает достаточно большой перечень приложений и баз данных, (см. ссылку справа вверху страницы) и при этом саппорт и админы достаточно адекватные люди и помогают решать различные вопросы, в то время как на других хостингах как правило или не знают что делать или просто говорят что они не поддерживают что-то. При установке Django я руководствовался статьей с wiki хостинг-провайдера Dreamhost, кроме этого мне очень помогли в выявлении причин различных ошибок сотрудники компании "Хостинговые телесистемы" в связи с чем хотелось бы поблагодарить их за это :-) Собственно установка Django: в данном случае предпложим что
- home директория: /home/username/
- сайт и все доступные извне файлы находятся в каталоге: /home/username/domain.ru
- media файлы мы будем хранить в каталоге: /home/username/media/domain, файлы находящиеся в этом каталоге будут доступны по адресу http://media.domain.ru/ (о том как настроить домен, можно почитать в FAQ)
- все наши проекты будут храниться в каталоге: /home/username/django_projects/
- наш тестовый проект будет называться myproject
- шаблоны будут храниться в каталоге /home/username/django_templates/myproject
Создаем каталог где будем временно хранить файлы для установки django и модулей, и каталог куда мы все это будем устанавливать
$ cd $ mkdir build python
Скачиваем Django, модуль для работы с PostgreSQL и модуль для работы с FastCGI и устанавливаем их
$ cd build $ wget http://www.djangoproject.com/download/0.96/tarball/ && wget http://initd.org/pub/software/psycopg/psycopg2-2.0.6.tar.gz && wget http://www.saddi.com/software/flup/dist/flup-0.5.tar.gz $ tar zxf Django-0.96.tar.gz $ tar zxf psycopg2-2.0.6.tar.gz $ tar zxf flup-0.5.tar.gz $ cd Django-0.96 $ python setup.py install --prefix /home/username/python $ cd ../psycopg2-2.0.6 $ python setup.py install --prefix /home/username/python
после того как они установились в каталоге /home/username/python появятся две папки - bin и lib, в папке bin лежит django-admin.py в папке libs появляется еще несколько папок среди которых /home/username/python/lib/python2.4/site-packages и /home/username/python/lib/python2.4/site-packages/psycopg2
С flup такой метод установки не сработал, поэтому он устанавливается таким образом:
$ cp ~/build/flup-0.5/flup/server/fcgi.py ~/python/lib/python2.4/site-packages/ $ cp -R ~/build/flup-0.5/flup/ ~/python/lib/python2.4/site-packages/flup
Теперь необходимо внести изменения в переменные окружения, я пользуюсь bash поэтому настройки написаны для этого интерпретатора. Редактируем /home/username/.bashrc и добавляем в него следующие строки:
export PATH=$PATH:$HOME/python/bin:$HOME/python/lib/python2.4/site-packages export PYTHONPATH=$PYTHONPATH:$HOME/python/lib/python2.4/site-packages:$HOME/django_projects:
после чего нужно перезагрузить конфиг
$ source .bash_profile
Теперь можно проверить правильно ли все установлено:
$ python Python 2.4.4 (#2, Jun 6 2007, 17:41:44) [GCC 3.4.6 [FreeBSD] 20060305] on freebsd6 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path.append('/home/username/python/lib/python2.4/site-packages') >>> sys.path.append('/home/username/django_projects') >>> import psycopg2 >>> from fcgi import WSGIServer
на этом этапе никаких ошибок не должно появится. Если копировать код отсюда и вставлять в консоль то может появится пробел в начале строки это вызовет ошибку типа во такой
File "", line 1 import psycopg2 ^ SyntaxError: invalid syntax
Django будет работать через FastCGI для включения соответствующих настроек необходимо создать файл /home/username/domain.ru/dispatch.fcgi c таким содержанием:
#!/usr/local/bin/python import sys sys.path.append('/home/username/python/lib/python2.4/site-packages') sys.path.append('/home/username/django_projects') from fcgi import WSGIServer from django.core.handlers.wsgi import WSGIHandler import os os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' WSGIServer(WSGIHandler()).run()
после чего выставить ему необходимые для корректной работы права
$ chmod 750 ~/domain.ru/dispatch.fcgi
в файл /home/username/domain.ru/.htaccess необходимо добавить:
Options +ExecCGI AddHandler fastcgi-script .fcgi RewriteEngine On RewriteBase / RewriteRule ^(dispatch\.fcgi/.*)$ - [L] RewriteRule ^(.*)$ dispatch.fcgi/$1 [L]
Различные media-файлы мы будем хранить в /home/username/media/domain/ кроме этого когда мы работаем в административном интерфейсе Djungo различные media-например css хранятся в отдельной папке, местонахождение которой задается в настройках нашего проекта, речь о которых пойдет ниже. Для того чтобы они были доступны мы создадим symlink на соответствующую директорию в дистрибутиве django:
$ ln -s $HOME/home/username/python/lib/python2.4/site-packages/django/contrib/admin/media/ $HOME/media/myproject/admin_media
Теперь о настройках, для начала нужно создать новый проект, создать папку где мы будем хранить проекты и папку для шаблонов:
$ mkdir ~/django_projects ~/django_templates $ cd ~/django_projects $ django-admin.py startproject myproject
После этого появляется папка myproject, в ней редактируем файл /home/username/django_projects/myproject/settings.py я использовал в качестве базы PostgreSQL для MySQL соответсвенно нужно выбрать DATABASE_ENGINE = 'mysql' и DATABASE_PORT = 3306
DATABASE_ENGINE = 'postgresql_psycopg2' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. DATABASE_NAME = 'djungo_db' # Or path to database file if using sqlite3. DATABASE_USER = 'djungo_user' # Not used with sqlite3. DATABASE_PASSWORD = 'Wk7hhL2I' # Not used with sqlite3. DATABASE_HOST = 'database_host' # Set to empty string for localhost. Not used with sqlite3.
После этого можно запускать синхронизацию с БД, после успешного завершения которой будет предложено создать административный аккаунт:
$ cd ~/django_projects/myproject/ $ 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 Creating table django_admin_log 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 'boris'): someuser E-mail address: contact@somesite.ru Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model
После этого можно попробовать загрузить страницу http://www.domain.ru/admin/ - все должно работать. ps: в официальном руководстве указано что необходимо запустить свой сервер на время разработки командой python manage.py runserver. Ничего это делать не нужно, административный интерфейс будет и так доступен после выполнения всех перечисленных выше действий.
Ошибка 500 при работе с Django через FastCGI (решение)
В логах ошибка выглядит так:
[Fri Sep 28 00:43:49 2007] [error] [client 85.141.235.249] FastCGI: comm with (dynamic) server "/storage/home/username/domain.ru/dispatch.fcgi" aborted: (first read) idle timeout (30 sec) [Fri Sep 28 00:43:49 2007] [error] [client 85.141.235.249] FastCGI: incomplete headers (0 bytes) received from server "/storage/home/username/domain.ru/dispatch.fcgi"
Одна из причин возникновения подобных ошибок - неправильный путь к Python. Для того чтобы определить путь к Python можно воспользоваться командой whereis:
$ whereis python python: /usr/local/bin/python /usr/local/man/man1/python.1.gz /usr/ports/lang/python
Несколько особенностей при использовании Django на виртуальном хостинге с FastCGI: например мы разрабатываем свой первый сайт при помощи официального руководства, создаем модель голосования (Polls), все сохраняем, заходим на сайт и видим разноцветную фиолетово-синюю страницу с ошибкой:
TemplateDoesNotExist A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.
На Dreamhost wiki на этот случай написан совет убить python командой pkill python, но у меня она не сработала, видимо по причине того что fcgi, python работают от пользователя www-server или какого то еще.
Решение этой проблемы:
- в каталоге cgi-bin создаем скрипт с таким содержанием
ставим правильные права ($chmod 750 kill_python2ADF23x.sh)запускаем его http://www.domain.ru/cgi-bin/kill_python2ADF23x.sh Имя файла скрипта специально содержит случайные символы чтобы его не запустил кто-то, не знающий этого имени.- #!/bin/sh
- killall python
- после этого необходимо убить все byte-compled файлы, которые создает python:
- cd ~/django_projects/
- $ find ./ -name \*.pyc -type f -exec rm {} \;
- $ find ./ -name \*.pyo -type f -exec rm {} \;
- $ touch ~/domain.ru/dispatch.fcgi ~/build/flup-0.5/flup/server/fcgi.py
На всякий случай полезно очистить кэш браузера и обновить страницу, если глюки продолжаться то необходимо выпоснить приведенные выше команды find ... в корневой директории где установлен сам django.





Последние комментарии
2 weeks 5 days ago
2 weeks 5 days ago
2 weeks 5 days ago
2 weeks 5 days ago
4 weeks 12 hours ago
4 weeks 4 days ago
5 weeks 1 day ago
5 weeks 4 days ago
6 weeks 3 days ago
6 weeks 6 days ago