 日記APIを作成し、公開するところまでを初期の状態からやっていきます。
日記APIを作成し、公開するところまでを初期の状態からやっていきます。
完成品はこちらです。実際に僕が日記を運用しているAPIです。 笑
笑
http://www.kojimaiton-philosophy.com/api/diaries/
 日記REST_APIの使い方
日記REST_APIの使い方
CRUDで日記に必要な最低限の機能を提供します 
GETは誰でも取得可能だが、POST``PUT``DELETEは誰からでもアクセスさせるわけにはいかないので、アクセストークンをヘッダーに付ける。
XXXXXX_XXXXXX のところを取得したアクセストークンに置き換える。
GET
リストで日記を取得。 ページネーション、 フィルター、 リミット・オフセットも使用可能。
$ curl http://localhost/api/diaries/
日付を主キーにして、日付の日記一件を取得。
$ curl http://www.kojimaiton-philosophy.com/api/diaries/2016-12-19/
POST
日記に必要な内容を入れて、新規で作成する  ※日付を主キーにしているので、同じ日付は二回POSTできない。
$ curl -X POST http://www.kojimaiton-philosophy.com/api/diaries/ -d "date=2017-03-25" -d "title=日記のタイトル" -d "body=日記の内容" -d "publishing=true" -H "Authorization: JWT XXXXXX_XXXXXX"`
PUT
更新したい日付をパスに指定して、変更したいデータに書き換えて更新する。
$ curl -X PUT http://www.kojimaiton-philosophy.com/api/diaries/2017-03-25/ -d "date=2017-03-25" -d "title=日記のタイトルの変更" -d "body=日記の変更" -d "publishing=false" -H "Authorization: JWT XXXXXX_XXXXXX"
DELETE
削除したい日付をパスに指定して、データを削除。
$ curl -X DELETE http://www.kojimaiton-philosophy.com/api/diaries/2017-03-25/ -H "Authorization: JWT XXXXXX_XXXXXX"
 環境
 環境
CentOS: 7.3.1
Python: 3.6.0
Django: 1.10.6
Restframework: 3.6.2
MySQL: 5.7.17
Nginx: 1.11.13
 設定
設定
基本設定
yumをアップデート
$ sudo yum update -y
gitをインストール
$ sudo yum install git -y
必要なライブラリを入れておく
$ sudo yum install zlib-devel bzip2 bzip2-devel readline-devel openssl-devel sqlite3 sqlite-devel gcc -y
ポート関連の設定
練習のためにfirewalldを切っておく
$ systemctl stop firewalld
firewalld自動起動停止
$ systemctl disable firewalld
SELinixの確認
$ getenforce
もし Enforcingの場合は、 以下で編集しSELINUX=enforcingをSELINUX=disabledに書き換える。
$ sudo vi /etc/selinux/config
書き換えた場合は設定を反映させるためにマシンを再起動
$ sudo shutdown -r now
Disabledであることを確認する
$ getenforce
pyenvのインストール
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ exec $SHELL -l
確認
$ pyenv -v
pythonのインストール
バーションを確認
$ pyenv install -l
今回は 3.6.0 インストール ※インストールが終わるのにかなり時間が掛かる
$ pyenv install 3.6.0
確認
$ pyenv versions
デフォルトを変更
$ pyenv global 3.6.0
確認
$ pyenv versions
Djangoと使用するライブラリのインストール
Djangoのインストール(python3.6からはpipがデフォルトで使用可能)
$ pip install django
REST_Frame_Workのインストール
$ pip install djangorestframework
フィルタリング
$ pip install django-filter
JWTによるアクセストークン
$ pip install djangorestframework-jwt
Djangoでmysqlを塩う
$ pip install PyMySQL
Djangoを本番サーバーで実行
$ pip install uwsgi
 Djangoプロジェクトの作成
Djangoプロジェクトの作成
プロジェクトを作成
$ django-admin startproject django_rest_framework
$ cd django_rest_framework
ホスト名を修正。自分で使っているIP・ドメインを入れる事。
$ sudo vi django_rest_framework/settings.py
ALLOWED_HOSTS = ['160.16.65.138', 'localhost', '127.0.0.1',]
manage.pyファイルがあるディレクトでサーバーを起動し、ブラウザで接続を確認する。 http://ドメイン名:8000 で確認できる。 サーバーの終了はCtrl+C
$ python manage.py runserver 0.0.0.0:8000
サーバー起動中はsettings.pyのdebugモードがデフォルトでtrueになっているので、ファイルを編集すれば、即サーバーに反映される。
 DBの設定
DBの設定
CentOS側のDBの設定
SQLiteを使えば手軽だが、ここではしっかりと汎用的に使えるMySQLを採用します。(設定が長いですが )
)
先ほど、実行してできてしまったdb.sqlite3を削除する。 
$ ls
db.sqlite3  diary  manage.py
$ rm db.sqlite3
centos7からはmariaDBがデフォルト入っているので、削除
$ sudo yum remove mariadb-libs -y
別バージョンのmysqlを使用していた場合、そのデータが残っている可能性があるため削除
$ rm -rf /var/lib/mysql/
MySQLのリポジトリを追加
$ sudo yum -y install http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
インストール可能な内容を確認
$ yum repolist enabled | grep "mysql.*-community.*"
infoコマンドで情報を確認
$ yum info mysql-community-server
インストール
$ sudo yum -y install mysql-community-server
バージョン確認
$ mysql --version
自動起動
$ sudo chkconfig mysqld on
起動
$ sudo systemctl start mysqld
デフォルトのパスワードの確認
$ sudo vi /var/log/mysqld.log
log ファイルから以下の仮のパスワードを見つけ出す。 今回、自分のパスワードは (E,irsThV0uB のようだ
2017-04-01T20:05:05.561190Z 1 [Note] A temporary password is generated for root@localhost: N4IYvEp&)6%!
以下を実行するとパスワードを求められるので、上記で見つけ出したパスードを入力する
$ mysql -u root -p
仮パスワードを変更しないと、一切の処理を受け付けてくれないので変更する。 ただしこのパスワードは8文字以上、英字、数字、記号をそれぞれ含めないといけないと受け付けてくれないので、注意。
$ ALTER USER root@localhost IDENTIFIED BY '@Mysql0001';
設定されたら、mysqlを一旦exit
$ exit;
以下のファイルに一行加えて日本語設定をする。 [mysqld]の下に、character-set-server=utf8 を追加。
$ sudo vi /etc/my.cnf
記述はこんな感じ↓
[mysqld]
character-set-server=utf8
設定を反映
$ sudo systemctl restart mysqld
Djangoで使用するためのDBを作成する
$ mysql -u root -p
ここではdiarydbという名前にする。
$ create database diarydb;
作成したら終了
$ exit
Django側のDB設定
settings.pyを編集
$ vi django_rest_framework/settings.py
import os
# pymysqlをimportする
import pymysql
# mysqlを使用するように変更
pymysql.install_as_MySQLdb()
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.mysql',
       # データベース名
       'NAME': 'diarydb',
       # ユーザー名
       'USER': 'root',
       # パスワード
       'PASSWORD': '@Mysql0001',
       # サーバのIPアドレスやホストを。空欄はローカルホスト
        'HOST': '',
       # ポート
       'PORT': '3306',
       'OPTIONS': {
           # 制約を厳しくチェック
           'sql_mode': 'traditional',
       },
       # テスト用ユーザー
        'TEST_NAME': 'auto_tests',
   }
}
DjangoとMySQLが接続できるか確認
migrationファイルを作る
$ python manage.py makemigrations
migrationファイルを元にDBに反映する
$ python manage.py migrate
DBの設定が終了...長い
 Djangoプロジェクトを編集
Djangoプロジェクトを編集
日記appを作成
$ cd django_rest_framework
$ python manage.py startapp diary
現状のディレクトリ構成はコチラ。大枠ここに少しづつファイルを足す感じです
└── django_rest_framework
    ├── diary
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── django_rest_framework
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-36.pyc
    │   │   ├── settings.cpython-36.pyc
    │   │   ├── urls.cpython-36.pyc
    │   │   └── wsgi.cpython-36.pyc
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py
モデルを定義
モデルはDBと一対一になる。
models.py を作成
$ vi diary/models.py
# coding: utf-8
from django.db import models
from datetime import date
class Diary(models.Model):
    date = models.DateField(default=date.today, primary_key=True)
    title = models.CharField(max_length=128)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    publishing = models.BooleanField(default=True)
作成した model を settings.py に定義
$ vi django_rest_framework/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # diaryを追加
    'diary',
]
もう一度DBをマイグレーション
$ python manage.py makemigrations
$ python manage.py migrate
DjangoのDBの管理画面に入る
admin用のユーザー作成
$ python manage.py createsuperuser
サーバーを起動。
$ python manage.py runserver 0.0.0.0:8000
管理画面にアクセス http://自分のIP・ドメイン:8000/admin/
先ほど createsuperuser で作成した Username と Password を入力して管理画面に入る。
GUIをポチポチして、モデルを編集したり、追加したりできます。
ここに先ほど作成したモデルもGUIから操作できるように加えます。
$ vi diary/admin.py
# coding: utf-8
from django.contrib import admin
from .models import Diary
@admin.register(Diary)
class Diary(admin.ModelAdmin):
    pass
管理画面に DIARY が加わっています
APIで使用するために、ここで日記をいくつか作って置きましょう。
Diarys -> Add diary -> SAVE
 REST frameworkの導入
REST frameworkの導入
REST frameworkを定義
$ vi django_rest_framework/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # diaryを追加
    'diary',
    # frameworkを追加
    'rest_framework',
]
Serializerを定義
APIへの出力対象のフィールドは Serializerクラス内で制限する
$ vi diary/serializer.py
# coding: utf-8
from rest_framework import serializers
from .models import Diary
class DiarySerializer(serializers.ModelSerializer):
    class Meta:
        model = Diary
        fields = ('date', 'title', 'body', 'publishing',)
ViewSetを定義
ViewSetはコントローラー
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
class DiaryViewSet(viewsets.ModelViewSet):
    queryset = Diary.objects.all()
    serializer_class = DiarySerializer
Urlsを定義
UrlsはURLのルーター設定
作成したDiaryViewSet を登録する
$ vi diary/urls.py
# coding: utf-8
from rest_framework import routers
from .views import DiaryViewSet
router = routers.DefaultRouter()
router.register(r'diaries', DiaryViewSet)
外部からアクセスされるルーティーングの設定
$ vi django_rest_framework/urls.py
# coding: utf-8
from django.conf.urls import url, include
from django.contrib import admin
from diary.urls import router as diary_router
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(diary_router.urls)),
]
実行して確認してみる
サーバーを立ち上げる
$ python manage.py runserver 0.0.0.0:8000
ブラウザで接続
http://自分のIP・ドメイン:8000/api/diaries/
curlで叩くと、jsonが返ってきている。
$ curl http://160.16.65.138:8000/api/diaries/
[{"date":"2017-04-15","title":"タイトルテスト","body":"中身テスト","publishing":true},{"date":"2017-04-16","title":"タイトル","body":"中身!","publishing":true}]
ここで注意点ですが、上記の写真のGET横のボタンでプルダウンからjsonで見ると文字化けします。
Chromeのバージョンによっては文字化けしてないかもしれませんが、それは自動でUTF-8に変換してくれているからです。
SafariなどでUTF-8指定をしないまま見ると、文字化けしていると思います。
下記を直すにはクライアントに返すjsonにUTF-8をこちらで指定しなければいけません。
jsonをutf-8指定にする
REST Framework のドキュメントにはデフォルトでUTF-8と書いてあるが
$ vi diary/renderers.py
UTF-8を指定したUTF8CharsetJSONRendererクラスの作成
デフォルトのrest_framework.renderers.JSONRenderer でUTF-8になっていそうだが、出来なかった。。。
from rest_framework.renderers import JSONRenderer
class UTF8CharsetJSONRenderer(JSONRenderer):
    charset = 'utf-8'
settings.pyに以下を追記
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'diary.renderers.UTF8CharsetJSONRenderer',
    )
}
文字化けが直った
 CURDの確認
CURDの確認
IPの所は自分のに変更してリクエストする事
POST(Create)
新規作成
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-22" -d "title=日記のタイトル" -d "body=POSTのテスト" -d "publishing=true"
PUT(Update)
更新
$ curl -X PUT http://160.16.65.138:8000/api/diaries/2017-04-22/ -d "date=2017-04-22" -d "title=日記のタイトルの変更" -d "body=PUTのテスト" -d "publishing=false"
GET(Read)
リストの取得
$ curl http://160.16.65.138:8000/api/diaries/
日付で取得
$ curl http://160.16.65.138:8000/api/diaries/2017-04-22/
DELETE(Delete)
削除
$ curl -X DELETE http://160.16.65.138:8000/api/diaries/2017-04-22/
 ページネーション
ページネーション
ページネーションを追加
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
    # 追加
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,
    'DEFAULT_RENDERER_CLASSES': (
        'diary.renderers.UTF8CharsetJSONRenderer',
    )
}
取得するとjsonのルートにnextとpreviousが追加され、前後のページを辿れる。
$ curl http://160.16.65.138:8000/api/diaries/
{
    count: 4,
    next: "http://160.16.65.138:8000/api/diaries/?limit=3&offset=3",
    previous: null,
    results: [
        {
            date: "2017-04-15",
            title: "タイトルテスト",
            body: "中身テスト",
            publishing: true
        },
        {
            date: "2017-04-16",
            title: "タイトル",
            body: "中身!",
            publishing: true
        },
        {
            date: "2017-04-21",
            title: "hoge",
            body: "ssss",
            publishing: true
        }
    ]
}
 フィルター
フィルター
views.py を編集
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
class DiaryViewSet(viewsets.ModelViewSet):
    queryset = Diary.objects.all()
    serializer_class = DiarySerializer
    # フィルタを追加
    filter_fields = ('publishing',)
settings.pyを編集
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
    # フィルター追加
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
    # ページネーション追加
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,
    'DEFAULT_RENDERER_CLASSES': (
        'diary.renderers.UTF8CharsetJSONRenderer',
    )
}
公開フラグをfalseのものだけフィルタしてみる ?publing=false をリクエストに付ける
$ curl http://160.16.65.138:8000/api/diaries/?publing=false
{
    count: 1,
    next: null,
    previous: null,
    results: [
        {
            date: "2017-04-22",
            title: "hogehoge",
            body: "hoge",
            publishing: false
        }
    ]
}
 認証
認証
認証方法は色々あるが今回はJWT(Json Web Token)を使用
settings.pyを編集
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
    # JWTの認証追加
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    'NON_FIELD_ERRORS_KEY': 'detail',
    'TEST_REQUEST_DEFAULT_FORMAT': 'json',
    # フィルター追加
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
    # ページネーション追加
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,
    'DEFAULT_RENDERER_CLASSES': (
        'diary.renderers.UTF8CharsetJSONRenderer',
    )
}
# JWTの認証追加
JWT_AUTH = {
    # トークンの期限をここでは無効にしてみる
    'JWT_VERIFY_EXPIRATION': False,
}
urls.py を編集
$ vi django_rest_framework/urls.py
# coding: utf-8
from django.conf.urls import url, include
from django.contrib import admin
from diary.urls import router as diary_router
# 認証を追加
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(diary_router.urls)),
    # 認証を追加
    url(r'^api-auth/', obtain_jwt_token),
]
JWTのアクセストークンの取得
createsuperuserで作成したadmin ユーザーのusernameとpasswordを入れてリクエスト
$ curl http://160.16.65.138:8000/api-auth/ -d "username=XXXXXXX&password=XXXXXXXX"
成功した場合レスポンスにtokenが入ってくる。
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6Im11dS5rb2ppbWEudGVzdEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6ImRqYW5nbyIsImV4cCI6MTQ5Mjg1NTMxMH0.m07BcTiAkA79HZ0BC8BsgYOA-SbqmC5GMN5g_QBizZw"}
ユーザー名やパスワードが違うと以下のように失敗する
{"detail":["Unable to login with provided credentials."]}
views.py を編集し、認証を掛ける
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
# 認証追加
from rest_framework import permissions
class DiaryViewSet(viewsets.ModelViewSet):
    queryset = Diary.objects.all()
    serializer_class = DiarySerializer
    # フィルタを追加
    filter_fields = ('publishing',)
    # 認証追加 CURD全てに認証掛けたい場合は (permissions.IsAuthenticated,)にする
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
認証が掛かっているか試す
新規作成
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-21" -d "title=認証" -d "body=認証のテスト" -d "publishing=true"
アクセストークンがないので以下のように失敗すればOK!
{"detail":"Authentication credentials were not provided."}
取得したアクセストークンを付けてPOSTする ※アクセストークンは自分のに変えること
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-10" -d "title=認証" -d "body=認証のテスト" -d "publishing=true" -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6Im11dS5rb2ppbWEudGVzdEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6ImRqYW5nbyIsImV4cCI6MTQ5Mjg1NTMxMH0.m07BcTiAkA79HZ0BC8BsgYOA-SbqmC5GMN5g_QBizZw"
作成できたら、GET以外全てに認証が掛かっているかを確認する
※ 参考permissions.IsAuthenticatedOrReadOnly なので、 OrReadOnly を取れば、GET にも認証が掛かる。
404ページを通常のに修正。
現状ルートにアクセスすると、Djangoのデフォルトでは以下のようになる
http://160.16.65.138:8000/
下の方の文言通りに、 settings.pyを編集し、DEBUG = False に設定する ※ DEBUG = Falseにするとサーバーを起動しながら、自動でファイルの変更を反映する事ができないので注意
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
$ vi django_rest_framework/settings.py
...省略
# DEBUG = Falseにすると通常の404ページになる
DEBUG = False
...省略
アクセスすると通常の404ページになった!
 テストケース
テストケース
tests.pyを削除
$ rm diary/tests.py
テスト用ディレクトリ作成。ここにテストを入れる
$ mkdir diary/tests
pythonのディレクトリと認識されるように`__init__.py` を追加。 特に何も記述はしない。
$ vi diary/tests/__init__.py
認証とCRUDのテストをするための test_diary.py を作成
$ vi diary/tests/test_diary.py
# coding: utf-8
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework_jwt.compat import get_user_model
from rest_framework_jwt.settings import api_settings
class DiaryTest(APITestCase):
    def setUp(self):
        # アクセストークンの発行
        User = get_user_model()
        self.username = 'test_user'
        self.email = 'test_user@gmail.com'
        self.user = User.objects.create_user(self.username, self.email)
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(self.user)
        token = jwt_encode_handler(payload)
        self.auth = 'JWT {0}'.format(token)
        self.url = '/api/diaries/'
    def test_diary_api(self):
        # POST
        data = {
            "date": "2011-11-11",
            "title": "title",
            "body": "body",
            "publishing": True,
        }
        response = self.client.post(self.url, data, HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data, data)
        # GET
        expected_get_data = {
            "count": 1,
            "next": None,
            "previous": None,
            "results": [
                {
                    "date": "2011-11-11",
                    "title": "title",
                    "body": "body",
                    "publishing": True,
                }
            ]
        }
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data, expected_get_data)
        # PUT
        data2 = {
            "date": "2010-10-10",
            "title": "title",
            "body": "body",
            "publishing": False,
        }
        response = self.client.put(self.url + '2011-11-11/', data2, HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data, data2)
        # DELETE
        response = self.client.delete(self.url + '2010-10-10/', HTTP_AUTHORIZATION=self.auth)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
テストを実行
以下を実行すると、 tests の中の test_xxxx.pyが実行される。
$ ./manage.py test
テストが通った!
[xxxxx@tk2-208-13884 django_rest_framework]$ ./manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.049s
OK
Destroying test database for alias 'default'...
 リバースプロキシの設定(APIのエンドポイントの:8000を消す)
リバースプロキシの設定(APIのエンドポイントの:8000を消す)
nginxのインストール
リポジトリを追加するので nginx.repo のファイルを作成
$ sudo vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
インストールと起動
nginxをインストール
$ sudo yum install nginx -y
バージョンの確認
$ nginx -v
自動起動設定
$ sudo systemctl enable nginx
起動
$ sudo systemctl start nginx
デフォルトページの確認
表示の確認をする。 http://自分のサーバーのIP/
以下は自分の例。
http://160.16.65.138/
※上記の index.html のデフォルトのパスは /usr/share/nginx/html/index.html
リバースプロキシを設定する
/etc/nginx/conf.d 以下に XXX.confという命名でファイルを作成する
ココでは server.conf とし、80 番で受けたリクエストを 8000 番に転送する
$ sudo vi /etc/nginx/conf.d/server.conf
server {
     listen 80;
     # アクセス可能なIPアドレス、もしくはドメイン。以下は自分の例
     server_name 160.16.65.138;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header Host $http_host;
     proxy_redirect off;
     proxy_max_temp_file_size 0;
     location / {
        # 転送先
        proxy_pass http://localhost:8000;
     }:joy:
}
nginx再起動させ設定を反映させる
$ sudo systemctl restart nginx
実行すると、ブラウザからはデフォルトHTTPの80でアクセスできる用になるので、 8000が不要になる
python manage.py runserver 0.0.0.0:8000
 Djangoをデーモンで起動し、本番環境で実行する
Djangoをデーモンで起動し、本番環境で実行する
サーバーからexitしてもバックグラウンドで動き続けるようにしてみる。
ルートにパスワードを設定
$ sudo passwd root
ルートになる
$ su
本番環境のデーモンでDjangoを実行
$ uwsgi --http :8000 --module django_rest_framework.wsgi --daemonize /var/log/uwsgi-django.log
以上で、バックグラウンドで動いているはず!
バックグラウンドで動いているuwsgiの止め方は動かしてるサーバーのPIDをkillする。
調べる
$ netstat -ntlp
uwsgi の横に表示されているが、PIDなので、
この場合は kill -9 32215 でサーバーが停止する
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      32181/nginx: master
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      861/sshd
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      32215/uwsgi
tcp        0      0 127.0.0.1:43047         0.0.0.0:*               LISTEN      32215/uwsgi
tcp6       0      0 :::22                   :::*                    LISTEN      861/sshd
tcp6       0      0 :::3306                 :::*                    LISTEN      19382/mysqld
uwsgi の読み方はウィスキーらしい?
"上杉"と読んでいた
 まとめ
 まとめ
Githubに完成品をあげて置きます 
実際に僕が日記を運用しているAPIです。 笑
笑
http://www.kojimaiton-philosophy.com/api/diaries/
拡張しつつ、生涯掛けて運用していきます
こちらはAWSで運用しています!
参考
http://qiita.com/redamoon/items/eabaacabb5b1a0c34ca3
http://qiita.com/seizans/items/05a909960820dd92a80a
http://racchai.hatenablog.com/entry/2016/05/08/070000
http://var.blog.jp/archives/70125676.html










