Docker – uwsgi – nginx – Django

 1. Assume
– Docker is already installed [Link]
– Django & it’s project is ready [Link]
– Postgres or MySQL is ready [Link]
– Python3
– CentOS 7

  2. Install Packages

yum install uwsgi
yum install nginx

 3. Create Uwsgi conf file
– Location : doesn’t matter , where you want..
– Name : whatever you want (*.ini)

[uwsgi]
project = firstsite
base = /home/user

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

socket = %(base)/%(project)/%(project).sock
chmod-socket = 664
vacuum = true

 4. Run Uwsgi

uwsgi ./<*.ini file> --emperor <Django Project Home> &

 5. Edit Nginx conf file
– Location : /etc/nginx/nginx.conf

server {
    listen <port>;
    server_name <servername>;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/dev/<project>/<project>/static;
    }

    location / {
        include         uwsgi_params;
        uwsgi_pass      unix:/home/dev/<project>/<project>.sock;
    }
}

 6. Run Nginx

/usr/sbin/nginx

 7. Test

http://<ip>:<port>

 

Apache – Django

A. Install packages

[python 2.7]

yum install httpd
yum install httpd-devel
yum install python-pip
pip install django
yum install mod_wsgi # case of python 2.7

[python 3.X]

yum install pcre-devel
wget http://mirrors.koehn.com/apache//httpd/httpd-2.4.23.tar.gz
tar xvzf httpd-2.4.23.tar.gz 
configure
make install

download site : https://github.com/GrahamDumpleton/mod_wsgi/releases

wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.7.tar.gz
tar xvzf 4.5.7.tar.gz
cd /<extract path>
./configure --with-apxs=/usr/local/apache2/bin/apxs
make install

B. Create Django Project

django-admin startproject django_demo

 C. Set mod_wsgi configuration

[python 2.7 – yum install httpd]

PATH : /etc/httpd/conf/

[python 3.x – manual install]

PATH : /usr/local/apache2

vi /etc/httpd/conf/httpd.conf

Listen <port>
IncludeOptional conf.d/*.conf
LoadModule wsgi_module modules/mod_wsgi.so

vi /etc/httpd/conf.d/django.conf

<VirtualHost *:80>

        WSGIScriptAlias / /opt/django_demo/django_demo/wsgi.py

        <Directory /opt/django_demo/django_demo>
        <Files wsgi.py>
                Require all granted
        </Files>
        </Directory>
</VirtualHost>

 D. Django wsgi.py

import os, sys


path = os.path.abspath(__file__+'/../..')

if path not in sys.path:

    sys.path.append(path)


from django.core.wsgi import get_wsgi_application


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_demo.settings")


application = get_wsgi_application()
chmod 777 /<path>/wsgi.py

E. Restart Apache

sudo service httpd.service restart

[manual start]

/usr/sbin/httpd

F. give permission

cat /etc/passwd | awk -F: '{print $1}' | grep apache

sudo visudo


----------------------------
apache  ALL=(ALL)       ALL

G. Log

/var/log/httpd

 

Django reset migration

If you want to remove all database migration settings and start from zero base
you can use “migrate –fake”.
Follow the bellow process will helps you to reset your jango database env.

[delete migration file]

go to your app folder then you will see folder name “migration” delete all the contents inside that folder except __init__.py

[make new migrations]

python manage.py makemigrations

[reset migration]

python manage.py migrate --fake <app-name> zero

[migrate new data base]

python manage.py migrate

 

 

DJango – templates & static

가. 시작하기

장고에서 뷰를 개발하려고 하면 통상적으로 필요한 것이  html, js, css, img 정도가 될 것이다. 그럼 장고에서는 이러한 파일들을 어떻게 관리하고 개발하는지 세팅 부분까지만 정리하고자 한다

나. template 정의하기

[setting.py]

DIRS 부분에 templates 폴더의 위치를 지정해 준다.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'tfmsaview/templates/')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
[urls.py]

아래 부분을 추가해 template 에 접근 할 수 있도록 한다

  url(r'^view/index/$', ui_view.UI_Service.as_view()),

[예제 전체]

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^nn/cnn/service/$', rest_view.CNN_Service.as_view()),
    url(r'^nn/cnn/config/$', rest_view.CNN_Config.as_view()),
    url(r'^nn/cnn/data/$', rest_view.CNN_Data.as_view()),
    url(r'^nn/cnn/stastics/$', rest_view.CNN_Stastics.as_view()),
    url(r'^view/index/$', ui_view.UI_Service.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
[폴더 및 파일 생성]

실제 폴더를 만들고 static 으로 사용할 파일을 넣어 준다. template 도 아까 정의한 것처럼 폴더를 생성하고 html 을 넣어 준다.

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-16-50

[html sample code]

template 안에서 static (js, css, img) 를 불러서 사용하려면 아래와 같은 패턴으로 사용하면 된다.

{% load staticfiles %}
{% static 'img/a.png' %}

아래는 전체 예제 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% load staticfiles %}
<img src="{% static 'img/a.png' %}" alt="My image"/>
</body>
</html>

 다. STATIC 정의하기

기본적으로 3가지 정의는 필요하다. root 는 실제 서비스시 서버에서 이미지를 제공할 경로가 된다. url 은 urls.py 에서 정의하게 되는데 웹에서 접속시 접속 경로가 된다. dirs 는 사용자가 이미지를 올리고자 하는 위치가 된다. 뒤에서 커맨드를 실행하면 dirs 에 있는 파일이 root 로 자동으로 옮겨지는 것을 볼 수가 있다.

[settings.py]
STATIC_ROOT = os.path.join(BASE_DIR , 'tfmsaview/')
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "tfmsaview/static"),
]
 [urls.py]

아래부분을 추가해 준다. 이는 직접적으로 url 을 통해 이미지 등에 접근 할 수 있도록 도와준다

+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^nn/cnn/service/$', rest_view.CNN_Service.as_view()),
    url(r'^nn/cnn/config/$', rest_view.CNN_Config.as_view()),
    url(r'^nn/cnn/data/$', rest_view.CNN_Data.as_view()),
    url(r'^nn/cnn/stastics/$', rest_view.CNN_Stastics.as_view()),
    url(r'^view/index/$', ui_view.UI_Service.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
[파일 생성]

settings.py 에 정의한 것 처럼 파일(js, css, img ) 등을 넣는다

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-16-50

[스태틱 파일들을 모아준다]

(/home/kim/anaconda2/) root@kim:~/PycharmProjects/TensorMSA# python manage.py collectstatic --noinput -i admin

 라. 테스트

다이렉트로 이미지에 접속도 잘 되었고, template 을 통한 이미지도 잘 접속 되었다.

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-26-34 %ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-26-46

 

Python – postgresql – Django – REST – TensorFlow 서비스 개발(2)

가. 지금까지 완료 된 것

– 1부 링크  : http://wp.me/p7xrpI-9h

– Anaconda 설치
– TensorFlow 설치
– Pycharm 설치
– postgresql 설치
– Django 설치
– Django Service 생성
– snippets APP 생성 완료
– Snippet Model 생성
– postgresql  동기화 완료

나.  Serializer

우리가 위에서 정의한  Snippet 데이터 클레스를 받아서  JSON 데이터로 변환하거나 ,
그 반대를 수행하는 클래스라고 생각하면 된다. 아래와 같이 프로젝트에 파일을 추가하고
콘솔을 실행하여 몇 가지 예를 테스트해보면 더 이해가 용이할 것이이다.

[Serializer 생성]

스크린샷, 2016-08-25 04-33-37

from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES


class SnippetSerializer(serializers.Serializer):
    pk = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    code = serializers.CharField(style={'base_template': 'textarea.html'})
    linenos = serializers.BooleanField(required=False)
    language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
    style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Snippet.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        instance.title = validated_data.get('title', instance.title)
        instance.code = validated_data.get('code', instance.code)
        instance.linenos = validated_data.get('linenos', instance.linenos)
        instance.language = validated_data.get('language', instance.language)
        instance.style = validated_data.get('style', instance.style)
        instance.save()
        return instance

 

[테스트 결과]

스크린샷, 2016-08-25 04-42-05

[디장고 쉘 실행]

python manage.py shell

 

[디비에 데이터 두건 삽입]

from snippets.models importSnippetfrom snippets.serializers importSnippetSerializerfrom rest_framework.renderers importJSONRendererfrom rest_framework.parsers importJSONParser snippet =Snippet(code='foo = "bar"\n') snippet.save() snippet =Snippet(code='print "hello, world"\n') snippet.save()

 

[정렬된 파이선 기본 데이터 타입]

serializer =SnippetSerializer(snippet) serializer.data

ReturnDict([('pk', None),
            ('title', u''),
            ('code', u'foo = "bar"\n'),
            ('linenos', False),
            ('language', 'python'),
            ('style', 'friendly')])

 

[정렬된 파이선 데이터를 JSON으로 변환]

content =JSONRenderer().render(serializer.data) content

'[{"pk":1,"title":"","code":"foo = \\"bar\\"\\n","linenos":false,"language":"python","style":"friendly"},{"pk":2,"title":"","code":"print \\"hello, world\\"\\n","linenos":false,"language":"python","style":"friendly"}]'

 

[JSON 파싱]

from django.utils.six importBytesIO stream =BytesIO(content) data =JSONParser().parse(stream)

 

[역정렬 – 데이터 객체로 만들고 다시 저장까지]

serializer =SnippetSerializer(data=data) serializer.is_valid()# True serializer.validated_data # OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]) serializer.save()# <Snippet: Snippet object>

 

[현재 디비에 저장된 모든 항목 출력]

serializer =SnippetSerializer(Snippet.objects.all(), many=True) serializer.data

Out[34]: [OrderedDict([('pk', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]

 

다. ModelSerializer 사용

위에서 정의한 꽤나 긴 Serialzier Code 를 아래와 같이 단순화 할 수 있다

class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style')

 

라.  views.py

실제로 서비스를 제공할 로직을 구현한다. 아래의 예제는  snippet_list 와  snippet_detail
두 가지 서비스에 대한 코드로 호출 주소에 대한 규칙은  urls.py 에 정의한다.
그리고 해당 메서드를 rest 로 정의하는 코드는 @api_view 로 처리하고자 하는 CRUD
를 정의하고 분기하여 처리한다.

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer



@api_view(['GET', 'POST'])
def snippet_list(request, format=None):
    """
    List all snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk, format=None):
    """
    Retrieve, update or delete a snippet instance.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

마. urls.py

from django.conf.urls import url
from django.contrib import admin
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

바. TEST

[snippet_list]

http http://127.0.0.1:8000/snippets/ Accept:application/json

스크린샷, 2016-08-25 06-38-41

[snippet_detail]

http form POST http://127.0.0.1:8000/snippets/ code=”print 123″

스크린샷, 2016-08-25 06-38-59

사. Class Based View

위 의 예제는 annotation 을 지정하여 사용하는 전형적인 REST 서버의 모습이었다고 하면, 클래스 형태로  REST  서비스를 구성하는 패턴도 있다

[views.py]

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class SnippetList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 

class SnippetDetail(APIView): """ Retrieve, update or delete a snippet instance. """ def get_object(self, pk): try: return Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: raise Http404 def get(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet) return Response(serializer.data) def put(self, request, pk, format=None): snippet = self.get_object(pk) serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): snippet = self.get_object(pk) snippet.delete() return Response(status=status.HTTP_204_NO_CONTENT)

 

[urls.py]

from django.conf.urls import url
from django.contrib import admin
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

Python – postgresql – Django – REST – TensorFlow 서비스 개발(1)

Anaconda , Django, Djangorestframework, Tensorflow, postgres 환경에서 REST API 호출을 통해  간단한 Tensorflow 예제를 실행하고 결과를 리턴하는 것까지 설명하고자 한다. Spark 연동 및 Tensorflow Serving 을 연동하는 부분은 따로 설명하겠다

[링크]
Anaconda – PyCharm – Tensorflow  환경 구성 : http://wp.me/p7xrpI-8Q

가. Anaconda sub Library Install

virtualenv 설정은 사용하지 않고 바로 설치하고 진행

[Django 설치]

conda install -c anaconda django=1.9.5

[Django Rest Frame Work]

conda install -c ioos djangorestframework=3.3.3

[postgress 연동 plugin]

conda install -c anaconda psycopg2=2.6.1

[pygments 설치]

conda install -c anaconda pygments=2.1.3

나. PostgresSql  설치

[설치]

yum install postgresql-server

[계정확인 / 비밀번호 지정]

cat /etc/passwd | grep postgres
 sudo passwd postgres

[DB  생성 경로 확인]

cat /var/lib/pgsql/.bash_profile
 env | grep PGDATA

[DB 초기화/실행]

sudo -i -u postgres
initdb
pg_ctl start
ps -ef | grep postgress

[DB 접속 / database 생성]

# psql
postgres=# create database test1  ;
postgres=# select *   from pg_database  ;

 

스크린샷, 2016-08-21 04-41-22

 

[user  생성 및 권한 부여 ]

postgres=#CREATE USER testuser WITH PASSWORD '1234';
postgres=#ALTER ROLE testuser SET client_encoding TO 'utf8'; 
postgres=#ALTER ROLE testuser SET default_transaction_isolation TO 'read committed'; postgres=#ALTER ROLE testuser SET timezone TO 'UTC';
postgres=#GRANT ALL PRIVILEGES ON DATABASE test1 TO testuser;


[생성 유저 테스트]

psql -U testuser test1

[psql command]

순서대로 전체 DATABASE LIST 출력, 선택한 DATABASE 접속, 해당 DATABASE TABLES

postgres=#\list 
postgres=#\connect DATABASE_NAME 
postgres=#\dl+

 

 다. Django 작업 목차

[1. 뼈대 구성]

startproject : 프로젝트 생성 
settings.py : 프로젝트 설정 항목 변경 
migrate : 유저/그룹 테이블 생성 
createsuperuser : 프로젝트 관리자 생성 
startaup : 북마크 앱 생성 
settings.py : 북마크 앱 등록

[2. 모델 코딩]

models.py : 모델(테이블)정의
admin.py : Admin 사이트에 모델 등록 
makemigrations  : 모델을 데이터베이스에 반영 
migrate

[3. 기타]

urls.py : URL 정의 
views.py : 뷰 로직 작성 
templates directory : 템플릿 파일 작성

라. 프로젝트 생성

[프로젝트 생성]

# cd ~/PycharmProjects 
# django-admin.py startproject djangodemo

 

마.북마크 앱 생성/등록

[북마크 앱 생성 ]

python manage.py startapp snippets

 

스크린샷, 2016-08-21 06-16-09

[북마크 앱 등록]

INSTALLED_APPS =(...'rest_framework','snippets.apps.SnippetsConfig',)

 

바. 디비 정보 세팅

[settings.py  수정 – 디비 정보 입력]

vi ~/PycharmProjects/djangodemo/djangodemo/settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'test1', 'USER': 'testuser', 'PASSWORD': '1234', 'HOST': 'localhost', 'PORT': '', } }

사. Model 생성

[models.py]

스크린샷, 2016-08-21 06-45-38

[예제 코드]

from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())


class Snippet(models.Model):
 created = models.DateTimeField(auto_now_add=True)
 title = models.CharField(max_length=100, blank=True, default='')
 code = models.TextField()
 linenos = models.BooleanField(default=False)
 language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
 style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)

 class Meta:
 ordering = ('created',)

아. Admin.py 등록

위에 정의한 테이블 구조에 맞춰 admin UI 에서도 볼 수 있도록 정의해 줍니다.

[admin.py]

from django.contrib import admin
from snippets.models import Snippet

# Register your models here.

class SnippetsAdmin(admin.ModelAdmin):
        list_display = ('created','title','code','linenos','language','style')

admin.site.register(Snippet, SnippetsAdmin)

차.  Project Migration

[migration]

python manage.py makemigrations 
python manage.py migrate

[reset migration]

python manage.py migrate --fake <app-name> zero

 

[실행 결과]

스크린샷, 2016-08-21 06-46-50

[Postgres DB Table 생성 확인]

마이그레이션은 기본적으로 디비와 모델을 동기화하는 작업

SELECT * FROM information_schema.tables ;
SELECT  <table name>  FROM information_schema.tables  ;

 

스크린샷, 2016-08-21 08-03-25

카. 슈퍼유저 생성 및 서버 테스트

[Create Super User]

python manage.py createsuperuser

[슈퍼유저 정보 입력]

Username (leave blank to use 'root'): kim
Email address: kim@naver.com
Password: 
Password (again): 

 

[Server Start]

프로젝트 폴더로 이동 (프로젝트 폴더에 manage.py   가 있는 위치) 하여   서버를 기동한다.

ip addr | grep "inet "
python manage.py runserver localhost:8989

 

 

 

스크린샷, 2016-08-21 05-53-58

[Admin Page]

http://등록한 주소 : 포트 /admin

계정은 아까 위에서 생성한 슈퍼 유저 (저는 OS 계정과 동일하게 설정)
위에서 생성한 테이블까지 출력된다면, 여기까지 문제없이 진행된 것

스크린샷, 2016-08-21 07-29-59

타. REST Service App 개발

– 참조 사이트 :  http://www.django-rest-framework.org/tutorial/1-serialization/

– 현재 상태
. snippets APP 생성 완료
. Snippet Model 생성
. postgresql  동기화 완료

==> 다음 포스트에서 작성