Nginx + uWSGI + Python + Django deployment instance

Keywords: Django Nginx Python MySQL

Nginx:

Nginx is a high-performance Web and reverse proxy server. It has many excellent features:

As a Web server: Compared with Apache, Nginx uses fewer resources, supports more concurrent connections and embodies higher efficiency, which makes Nginx especially popular with virtual host providers. Thanks to Nginx for choosing epoll and kqueue as our development model, we can support responses up to 50,000 concurrent connections.

As a load balancing server: Nginx can support Rails and PHP both internally and externally as an HTTP proxy server. Nginx is written in C, which is much better than Perlbal in terms of system resource overhead and CPU efficiency.

As a mail proxy server: Nginx is also a very good mail proxy server (one of the earliest purposes of developing this product is also as a mail proxy server). Last.fm describes successful and wonderful usage experience.

Nginx installation is very simple, configuration files are very simple (and can support perl syntax), Bugs very few servers: Nginx startup is particularly easy, and can almost run 7*24 uninterrupted, even if running for several months without rebooting. You can also upgrade software versions without interrupting service.

 

uWSGI:

  • APP is the application written by developers, such as django and bottle. Record how to process the logical part of the request sent by the client.

  • WSGI is a protocol that Python uses for Web development

  • uWSGI is a program that acts as a Web server or middleware.

  • If the architecture is Nginx+uWSGI+APP, uWSGI is a middleware

  • If the architecture is uWSGI+APP, uWSGI is a server

  • Uwsgi is a proprietary protocol implemented by uWSGI program.

Web protocols appear in sequence: 
CGI -> FCGI -> WSGI -> uwsgi

  1. CGI, the earliest protocol

  2. FCGI, faster than CGI

  3. WSGI, Python-specific protocol

  4. Uwsgi, faster than FCGI and WSGI, is the protocol of the UWSGI project. Its main feature is to use binary to store data. Previous protocols used strings, so they are better than string protocols in storage space and parsing speed.

 

 

Django:

    Django (Wikipedia) Django is an open source Web application framework written by Python. The software design pattern of MV C is adopted, namely model M, view V and controller C. It was originally developed to manage some of Lawrence Publishing Group's news-based websites. It was issued under BSD license in July 2005. The framework is named after Django Reinhardt, a Belgian Jazz Gypsy guitarist.

    Django's main goal is to make it easy to develop complex, database-driven websites. Django focuses on reusability and "pluggability" of components, agile development and DRY rule (Don't Repeat Yourself). Python is widely used in Django, including configuration files and data models.

           The core of the Django framework consists of an object-oriented mapper used as a data model (in Python) class Formal Definition) and Relevance data base Intermediate media; a regular expression-based URL distributor; a view system for processing requests; and a template system.

The core framework also includes:

l. A lightweight, stand-alone Web server for development and testing.

l. A form serialization and validation system for conversion between HTML forms and data suitable for database storage.

l. A caching framework with several caching options.

l. Middleware support that allows for interference in the various stages of request processing.

l. The built-in distribution system allows components of an application to communicate with each other using predefined signals.

l. A serialization system that generates or reads Django model instances expressed in XML or JSON.

l. A system for expanding the capabilities of template engines.


Main Characteristics of Django

  • Django Batteries-Included

            Django is based on the concept of "self-contained munitions". You don't need to use separate libraries to implement common functions, such as authentication, URL routing, template system, object relationship mapper (ORM) and database model migration. If you are using or have used Flask, you must notice that it needs to call other libraries, such as Flask-Login, to perform user authentication. This is not the case with Django.

  • Free API

    With Django, it's easy to generate Python API s based on your model. A simple command is enough to start generating an API without additional coding.

  • Unique Management Page

    Even before the site is fully built, you can get information from outside contributors. That's the power of Django. This framework enables you to quickly and easily generate management sites from application models.

  • Code Design

    Contrary to most Web frameworks, Django makes it easier to add new functionality to products by using something called app. Therefore, developers can feel that Django encourages you to write modular code.

  • Django's Perfect Support for ORM

            Django's Object Relation Mapping (ORM) provides perfect support for database. Therefore, when it is used to query the data needed by the database, it does not deal with the trouble of structured query language (SQL). Unlike many Python frameworks that work directly on databases through SQL, Django developers have a unique choice to manipulate the corresponding Python Model objects. Django can be used out of the box for databases such as PostgreSQL, MySQL, SQLite and Oracle.

  • Powerful built-in template system 

    Based on inheritance systems, Django's templates allow developers to build entire dynamic websites with very little front-end code. This benefits from the option of replacing certain elements of the template with other context-specific elements. Imagine, you know, every page of your website has a header and a footer. Now, you first need to write code in the basic template of the website. Then, you can dynamically change the components between the two contents from other parts of the application.

  • Simple Readable Web Sites

    Is it difficult to read the URL developed in PHP os ASP correctly? With Django, you can create easy-to-read URLs, which are good for both people and search engines. You can also use other frameworks to create readable URLs, but none of them are as easy to construct as Django.


    Django is a Python-written, advanced, MVC-style open source library. Django, also known as the "ultimate framework for perfectionists", was originally designed for news websites because it allows developers to write database-driven Web applications without coding from scratch.

  In addition to completing common Web development tasks faster, Django also keeps the design clean and practical. Django is the best choice for new Python Web developers because official documents and tutorials are the best of several (similar) software development frameworks.

  The technology market is full of a series of network frameworks, but Django is at the top of the most popular server-side Web frameworks. The motto behind designing Django is simple: avoid duplication. Django is written in Python, so it reduces too much middle-tier code and highlights efficiency. Django can support cloud platforms, making them a more popular choice in Web development.


Deployment of Nginx + uWSGI + Python + Django

nginx version: 1.5.9

Django version: 1.4.9

uwsgi version: 2.0.4

Python version: 2.6.6


Installation, Django, nginx, uwsgi, MySQL, compiled installation, easy to maintain

[root@kurol ~]# mkdir -p /data/logs
[root@kurol ~]# yum -y install gcc cc gcc-c++
[root@kurol ~]# tar -zxvf pcre-8.34.tar.gz
[root@kurol ~]# cd pcre-8.34
[root@kurol pcre-8.34]# ./configure
[root@kurol pcre-8.34]# make && make install
[root@kurol pcre-8.34]# cd ..
[root@kurol ~]# wget http://nginx.org/download/nginx-1.5.9.tar.gz
[root@kurol ~]# tar -zxvf nginx-1.5.9.tar.gz
[root@kurol ~]# cd nginx-1.5.9
[root@kurol nginx-1.5.9]# ./configure  --prefix=/usr/local/nginx --with-http_stub_status_module --without-http_gzip_module
[root@kurol nginx-1.5.9]# make && make install
[root@kurol nginx-1.5.9]# cd ..
[root@kurol ~]# yum -y install MySQL-python mysql mysql-devel mysql-server
[root@kurol ~]# yum -y install libxml2 python-devel
[root@kurol ~]# wget http://projects.unbit.it/downloads/uwsgi-2.0.4.tar.gz
[root@kurol ~]# tar -zxvf uwsgi-2.0.4.tar.gz
[root@kurol ~]# cd uwsgi-2.0.4
[root@kurol uwsgi-2.0.4]# make
[root@kurol uwsgi-2.0.4]# cp uwsgi /usr/bin
[root@kurol uwsgi-2.0.4]# cd ..
[root@kurol ~]# wget https://www.djangoproject.com/m/releases/1.4/Django-1.4.9.tar.gz --no-check-certificate
[root@kurol ~]# tar -zvxf Django-1.4.9.tar.gz
[root@kurol ~]# cd Django-1.4.9
[root@kurol Django-1.4.9]# python setup.py install


Configure Nginx.

[/usr/local/nginx/conf/nginx.conf]
server{
    listen 80;
    server_name www.mykurol.com;
        
    location / {
        uwsgi_pass 127.0.0.1:9001;
        include uwsgi_params;
        uwsgi_param UWSGI_CHDIR /data/www/board;
        uwsgi_param UWSGI_SCRIPT django_wsgi;
        access_log off;
}
        
    location ~* ^.+\.(mpg|avi|mp3|swf|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|txt|tar|mid|midi|wav|rtf|mpeg)$ {
        root /data/www/board/static;
        access_log off;
    }
}


Configure uwsgi.

[/usr/local/nginx/conf/uwsgi.ini]
[uwsgi]
socket = 0.0.0.0:9001
master = true
pidfile = /usr/local/nginx/uwsgi.pid
processes = 8
chdir = /data/www/board
pythonpath = /data/www
profiler = true
memory-report = true
enable-threads = true
logdate = true
limit-as = 6048
daemonize = /data/logs/django.log


Start Project board

[root@kurol logs]# cd /data/www/
[root@kurol www]# django-admin.py startproject board
[root@kurol www]# cd board/
[root@kurol board]# vim django_wsgi.py
#!/usr/bin python
# coding: utf-8
import os
import sys
reload(sys)
sys.setdefaultencoding('utf8')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "board.settings")
from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()
[root@kurol www]# ls
board
[root@kurol www]# tree
.
`-- board
    |-- board
    |   |-- __init__.py
    |   |-- settings.py
    |   |-- urls.py
    |   `-- wsgi.py
    `-- manage.py
2 directories, 5 files



Start uwsgi and nginx services, where uwsgi uses custom location profiles

[root@kurol ~]# /usr/bin/uwsgi --ini /usr/local/nginx/conf/uwsgi.ini 
/usr/bin/uwsgi: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory
[root@kurol ~]# ln -s /usr/local/lib/libpcre.so.1 /lib64
[root@kurol ~]# /usr/bin/uwsgi --ini /usr/local/nginx/conf/uwsgi.ini 
[root@kurol ~]# /usr/local/nginx/sbin/nginx
[root@kurol ~]# netstat -ltunp 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 0.0.0.0:9001                0.0.0.0:*                   LISTEN      15243/uwsgi         
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      15423/nginx         
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      868/sshd            
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      957/master


To facilitate service management, create nginx and uwsgi startup scripts.

nginx:

[root@kurol board]# touch /etc/init.d/nginx
[root@kurol board]# chmod 775 /etc/init.d/nginx
[root@kurol board]# vim /etc/init.d/nginx
#!/bin/sh
       #
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
       DESC="nginx daemon"
       NAME=nginx
       DAEMON=/usr/local/nginx/sbin/nginx 
       CONFIGFILE=/usr/local/nginx/conf/nginx.conf
       PIDFILE=/usr/local/nginx/logs/nginx.pid
       SCRIPTNAME=/etc/init.d/nginx
        
       # If the daemon file is not found, terminate the script.
       test -x $DAEMON || exit 0
       d_start(){
           $DAEMON -c $CONFIGFILE || echo -n " already running"
       }
       d_stop(){
           kill -QUIT `cat $PIDFILE` || echo -n " no running"
       }
       d_reload(){
           kill -HUP `cat $PIDFILE` || echo -n " could not reload"
       }
       case "$1" in
           start)
               echo -n "Starting $DESC: $NAME"
               d_start
               echo "."
               ;;
           stop)
               echo -n "Stopping $DESC: $NAME"
               d_stop
               echo "."
               ;;
           reload)
               echo -n "Reloading $DESC configuration..."
               d_reload
               echo "Reloaded."
               ;;
           restart)
               echo -n "Restarting $DESC: $NAME"
               d_stop
               # Sleep for two seconds before starting again, this should give the nginx daemon some time to perform a graceful stop
               sleep 2
               d_start
               echo "."
               ;;
           *)
               echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload)" >&2
               exit 3
               ;;
       esac
       exit 0


uwsgi:

[root@kurol board]# touch /etc/init.d/uwsgi
[root@kurol board]# chmod 775 /etc/init.d/uwsgi
[root@kurol board]# vim /etc/init.d/uwsgi
#!/bin/sh
       #
       set -e
       PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
       DESC="uwsgi daemon"
       NAME=uwsgi
       DAEMON=/usr/bin/uwsgi 
       CONFIGFILE=/usr/local/nginx/conf/uwsgi.ini
       PIDFILE=/usr/local/nginx/uwsgi.pid
       SCRIPTNAME=/etc/init.d/uwsgi
        
       # If the daemon file is not found, terminate the script.
       test -x $DAEMON || exit 0
       d_start(){
           $DAEMON --ini $CONFIGFILE || echo -n " already running"
       }
       d_stop(){
           kill -QUIT `cat $PIDFILE` || echo -n " no running"
       }
       d_reload(){
           kill -HUP `cat $PIDFILE` || echo -n " could not reload"
       }
       case "$1" in
           start)
               echo -n "Starting $DESC: $NAME"
               d_start
               echo "."
               ;;
           stop)
               echo -n "Stopping $DESC: $NAME"
               d_stop
               echo "."
               ;;
           reload)
               echo -n "Reloading $DESC configuration..."
               d_reload
               echo "Reloaded."
               ;;
           restart)
               echo -n "Restarting $DESC: $NAME"
               d_stop
               # Sleep for two seconds before starting again, this should give the nginx daemon some time to perform a graceful stop
               sleep 2
               d_start
               echo "."
               ;;
           *)
               echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload)" >&2
               exit 3
               ;;
       esac
       exit 0


Create a data model:

[root@kurol board]# cd /data/www/board/webserver/
[root@kurol webserver]# vim models.py
from django.db import models
class webserver(models.Model):
username = models.CharField('User name',max_length=30)
password = models.CharField('Password',max_length=30)
email = models.EmailField('E-mail',blank=True)
desc = models.TextField('describe',max_length=500,blank=True)
class Meta:
        db_table = u'board_webserver'
def __unicode__(self):
return self.username
[root@kurol webserver]# vim /data/www/board/board/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'OBServer',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '******',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }    
}  
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'webserver',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)


[root@kurol board]# export LC_ALL=en_US.UTF-8
[root@kurol board]# python manage.py sqlall webserver    #Check sql statements
BEGIN;
CREATE TABLE `board_webserver` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `username` varchar(30) NOT NULL,
    `password` varchar(30) NOT NULL,
    `email` varchar(75) NOT NULL,
    `desc` longtext NOT NULL
)
;
COMMIT;

No problem with the SQL statement, continue to execute

# Use migrate instead of syscdb in Django 1.9 and future versions.

syncdb will create all app s under INSTALL_APPS configured under set.py, create their corresponding data tables to the specified database, but only create nonexistent tables such as the above

        'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'webserver',

A corresponding table is created.

[root@kurol board]# python manage.py syncdb          
Creating tables ...
Creating table board_webserver
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)


Error Reporting

[root@kurol board]# python manage.py syncdb

TypeError: decode() argument 1 must be string, not None

Solve:

Write export LC_ALL=en_US.UTF-8 into profile or. bashrc.

[root@kurol board]# export LC_ALL=en_US.UTF-8


Generate applications, modify urls specified pages, and add views

[root@kurol webserver]# cd /data/www/board/
[root@kurol board]# python manage.py startapp webserver
[root@kurol board]# vim board/urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
    (r'^$', 'board.views.index'),
    (r'^board/', include('webserver.urls')),
)
[root@kurol board]# cd webserver/
[root@kurol webserver]# touch urls.py
[root@kurol webserver]# vim urls.py
from  django.conf.urls.defaults import *
urlpatterns = patterns('',
    (r'^$', 'webserver.views.index'),
    (r'^random_number/$', 'webserver.views.random_number'),
)
[root@kurol webserver]# cd ..
[root@kurol board]# cd board
[root@kurol board]# vim views.py
# Create your views here.
from django.http import HttpResponse
def index(request):
    html = """<html>
                <title>Main</title>
                <body>
                    <h1>Main Page</h1><hr>
                </body>
              </html>"""
    return HttpResponse(html)


The browser opens and shows that Main Page is successfully deployed.

Posted by Cliftron on Sat, 22 Jun 2019 17:50:08 -0700