python

Установка Django, PostgreSQL, Nginx на Debian сервере с нуля

Оригинал статьи размещен по адресу http://www.mindinmotion.ru/content/207.html

Решил снова попробовать Django. Некоторое время назад я перевел все сайты что начинал делать на Django на Drupal, либо на самописные решения, созданные с помощью Zend Framework. Тогда я руководствовался тем что надо хорошо знать какой один язык и забросил Python и Django. Сейчас все же решил снова вернутся к Django по нескольким причинам, во первых все таки многие вещи в Django делаются быстрее, ну например те же формы, даже используя Zend Form кода все равно в разы получается больше, особенно если валидаторы присобачивать, фильтры, кастомизировать как будет форма отображаться.

Ну вот как пример, кусок из одной партнерки которую я писал:

  1. $emailValidator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS, true);
  2.  
  3. $email = new Zend_Form_Element_Text('email');
  4. $email->setLabel('Email')
  5. ->setRequired(true)
  6. ->addFilter('StripTags')
  7. ->addFilter('StringTrim')
  8. ->addValidator($emailValidator)
  9. ->addErrorMessage('Ошибка: Email неправильный.');
  10. $email->setDecorators(array(
  11. 'ViewHelper','Description',
  12. 'Errors',
  13. array(array('data' => 'HtmlTag'), array('tag' => 'td')),
  14. array('Label', array('tag' => 'td')),
  15. array(array('row' => 'HtmlTag'),
  16. array('tag' => 'tr', 'openOnly' => false))
  17. ));

В общем ладно, перехожу к описанию установки Django, в качестве базы решил использовать PostgreSQL, лично для меня пофиг какая база PostgreSQL или MySQL, решил использовать PostgreSQL потому что сами разработчики Django когда разрабатывали свой фреймворк, затачивали его под Postgres.

  1. # aptitude install postgresql

Правим файл /etc/postgresql/8.4/main/postgresql.conf (здесь и дальше по тексту заменяем 8.4 на свою версию), меняем

  1. # listen_addresses = 'localhost'

на

  1. listen_addresses = 'localhost, 192.168.1.10'

В моем случае я прописываю внутренний айпишник сервера - 192.168.1.10

Дальше правим файл /etc/postgresql/8.4/main/pg_hba.conf, находим строку # IPv4 local connections:

добавляем

  1. host all all 192.168.1.1/24 md5

перезапускаем

  1. # /etc/init.d/postgresql-8.4 restart
  2. Restarting PostgreSQL 8.4 database server: main.

Если все сделали правильно Postgres начнет ждать подключений на нужном айпишнике.

  1. # netstat -tanp |grep postgre
  2. tcp 0 0 192.168.1.10:5432 0.0.0.0:* LISTEN 23104/postgres
  3. tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 23104/postgres
  4. tcp6 0 0 ::1:5432 :::* LISTEN 23104/postgres

Создаем нового юзера (в моем примере newuser) и зададим ему пароль qwerty

  1. # su postgres
  2. postgres@srv01:/etc/postgresql/8.4/main$ createuser newuser
  3. Shall the new role be a superuser? (y/n) n
  4. Shall the new role be allowed to create databases? (y/n) n
  5. Shall the new role be allowed to create more new roles? (y/n) n
  6. $ psql template1
  7. psql (8.4.1)
  8. Type "help" for help.
  9.  
  10. template1=# alter user newuser password 'qwerty';
  11. ALTER ROLE

Заодно сменим пароль для пользователя postgres

  1. template1=# ALTER ROLE postgres WITH ENCRYPTED PASSWORD 'my-super-secret-password';
  2. ALTER ROLE
  3. postgres=# \q

Создаем базу для пользователя newuser, на запрос пароля вводим пароль, который мы установили для пользователя postgres (my-super-secret-password)

  1. $ createdb websitedb --owner=newuser -hlocalhost
  2. Password:

Теперь пробуем подключиться с клиентской машины

  1. $ psql -Unewuser -W -hsrv01.lan
  2. Password for user newuser:
  3. psql (8.4.1)
  4. SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
  5. Type "help" for help.
  6.  
  7. newuser=>

С базой покончено, можно настраивать сайт

  1. # mkdir /var/www/yourwebsite
  2. # chown yourusername:yourusername /var/www/yourwebsite

Поясню этот шаг, у меня сервак используется для решения задач по разработке, так что я не ставлю целью сделать подобные проекты секьюрными и решаю вопросы по настройке сайтов исходя из того как мне удобно. Я монтирую директории по ssh и поэтому я меняю вдалельца каталогов на юзера yourusername - это тот юзер, которым я подключаюсь/монтирую по ssh этот проект.

Я использую Django из SVN, то есть самую последнюю версию, и я решил держать ее в той же директории, где будет находиться сайт. Тут есть одна особенность - сервер работает под юзером www-data, так что для директории с django я сменю owner на www-data, и туда же счекаютю последнюю версию Django, перед этим став юзером www-data.

  1. srv01:/var/www/yourwebsite# mkdir django-trunk
  2. srv01:/var/www/yourwebsite# chown www-data:www-data django-trunk/
  3. srv01:/var/www/yourwebsite# su www-data
  4. srv01:~/yourwebsite$ cd django-trunk/
  5. srv01:~/yourwebsite/django-trunk$
  6. $ svn co http://code.djangoproject.com/svn/django/trunk/ .
  7. A LICENSE
  8. A django
  9. A django/test
  10. A django/test/simple.py
  11. A django/test/client.py
  12. A django/test/testcases.py
  13.  
  14. ------------------- >8 вырезано -----------------------------
  15.  
  16. A examples/hello/urls.py
  17. A examples/views.py
  18. A examples/__init__.py
  19. A examples/settings.py
  20. A examples/urls.py
  21. A setup.cfg
  22. U .
  23. Checked out revision 11793.
  24. srv01:~/yourwebsite/django-trunk$ exit
  25. srv01:/var/www/yourwebsite#

Теперь нам надо узнать где находятся site-packages, для этого в консоли (в bash консоли, а не консоли python) надо набрать команду, приведеннуную ниже по тексту, в результате выполнения которой узнаем путь к site-packages.

  1. # python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
  2. /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 из любой директории.

  1. # ln -s `pwd`/django-trunk/django /usr/lib/python2.5/site-packages/django

Для запуска Django как FastCGI server понадобится flup, который можно установить из пакетов.

  1. # aptitude install python-flup

Создаем новый проект

  1. $ django-admin.py startproject yourproject
  2. boris@srv01:/var/www/yourwebsite$ ls -lha
  3. total 12K
  4. drwxr-xr-x 3 boris boris 4.0K Dec 4 13:55 .
  5. drwxrwxrwx 60 www-data www-data 4.0K Dec 4 00:58 ..
  6. drwxr-xr-x 2 boris boris 4.0K Dec 4 13:55 yourproject
  7. boris@srv01:/var/www/yourwebsite$ ls -lha yourproject/
  8. total 20K
  9. drwxr-xr-x 2 boris boris 4.0K Dec 4 13:55 .
  10. drwxr-xr-x 3 boris boris 4.0K Dec 4 13:55 ..
  11. -rw-r--r-- 1 boris boris 0 Dec 4 13:55 __init__.py
  12. -rwxr-xr-x 1 boris boris 546 Dec 4 13:55 manage.py
  13. -rw-r--r-- 1 boris boris 2.8K Dec 4 13:55 settings.py
  14. -rw-r--r-- 1 boris boris 550 Dec 4 13:55 urls.py

Проект создан, теперь можно запускать FastCGI сервер и настраивать Nginx.

  1. 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). Ниже содержимое этого файла:

  1. upstream djangoserv {
  2. server 127.0.0.1:3033;
  3. }
  4. server {
  5. listen 80;
  6. server_name yourwebsite;
  7. root /var/www/yourwebsite/yourproject;
  8.  
  9. access_log /var/www/ /logs/access.log;
  10. error_log /var/www/yourwebsite/logs/error.log;
  11.  
  12. 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) {
  13. access_log off;
  14. expires 30d;
  15. }
  16.  
  17. location / {
  18. fastcgi_pass 127.0.0.1:3033;
  19. fastcgi_param PATH_INFO $fastcgi_script_name;
  20. fastcgi_param REQUEST_METHOD $request_method;
  21. fastcgi_param QUERY_STRING $query_string;
  22. fastcgi_param SERVER_NAME $server_name;
  23. fastcgi_param SERVER_PORT $server_port;
  24. fastcgi_param SERVER_PROTOCOL $server_protocol;
  25. fastcgi_param CONTENT_TYPE $content_type;
  26. fastcgi_param CONTENT_LENGTH $content_length;
  27. fastcgi_pass_header Authorization;
  28. fastcgi_intercept_errors off;
  29. }
  30.  
  31. }

После чего делаем symlink и включаем конфиг для нового виртуал хоста, создаем папку с логами и выставляем ей нужного владельца (www-data), после чего перезагружаем nginx.

  1. srv01:/etc/nginx/sites-available# ln -s /etc/nginx/sites-available/yourwebsite /etc/nginx/sites-enabled/yourwebsite
  2. srv01:/etc/nginx/sites-available# mkdir /var/www/yourwebsite/logs
  3. srv01:/etc/nginx/sites-available# chown www-data:www-data /var/www/yourwebsite/logs
  4. # /etc/init.d/nginx reload
  5. Reloading nginx configuration: the configuration file /etc/nginx/nginx.conf syntax is ok
  6. configuration file /etc/nginx/nginx.conf test is successful
  7. nginx.

Если все сделали правильно теперь можно зайти по адресу http://yourwebsite и увидеть там дефолтную страницу Django с надписью It worked!

Еще по теме:  

Использование sqlite и Django

Создание каждой новой базы данных для нового веб-сайта на виртуальном хостинге довольно таки не дешевое занятие. Раньше при использовании Django я каждый раз заводил новую PosgreSQL базу, недавно зашел посмотрел во сколько мне это обходится, оказалось 841 рубль
В связи с тем что мои сайты потребляют очень мало трафика использовать полноценные базы данных смысла просто нет. Судя по информации на wiki sqlite использование этой базы данных оправдано для сайтов с посещаемостью до 10000 хитов в сутки.

Еще по теме:  

Ошибка 500 при работе с Django через FastCGI (решение)

В логах ошибка выглядит так:

  1. [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)
  2. [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:

  1. $ whereis python
  2. python: /usr/local/bin/python /usr/local/man/man1/python.1.gz /usr/ports/lang/python
После чего необходимо проверить содержимое файла ~/domain.ru/dispath.fcgi в самой первой строчке должно быть написано #!/usr/local/bin/python

Несколько особенностей при использовании Django на виртуальном хостинге с FastCGI: например мы разрабатываем свой первый сайт при помощи официального руководства, создаем модель голосования (Polls), все сохраняем, заходим на сайт и видим разноцветную фиолетово-синюю страницу с ошибкой:

  1. TemplateDoesNotExist
  2.  
  3. 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 создаем скрипт с таким содержанием
    1. #!/bin/sh
    2. killall python
    ставим правильные права ($chmod 750 kill_python2ADF23x.sh)запускаем его http://www.domain.ru/cgi-bin/kill_python2ADF23x.sh Имя файла скрипта специально содержит случайные символы чтобы его не запустил кто-то, не знающий этого имени.
  • после этого необходимо убить все byte-compled файлы, которые создает python:
    1. cd ~/django_projects/
    2. $ find ./ -name \*.pyc -type f -exec rm {} \;
    3. $ find ./ -name \*.pyo -type f -exec rm {} \;
    4. $ touch ~/domain.ru/dispatch.fcgi ~/build/flup-0.5/flup/server/fcgi.py

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

Последние комментарии