Django ~ Django REST frameworkを使ってみる
概要
Django REST frameworkを使って、Todoアプリを作ってみる。Qiitaの参考サイトをそのままやっています。めっちゃわかりやすい。
参考サイト
必要なパッケージのinstallと、djangoプロジェクトの下準備
- パッケージのinstallなど
$ pip install django $ pip install djangorestframework $ django-admin.py startproject django_rest_todo $ python manage.py migrate $ python manage.py createsuperuser $ django-admin.py startapp api # api用のappを作成しておく
- settings.pyを修正する。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'api', ] MIDDLEWARE = [ # 'django.middleware.security.SecurityMiddleware', # 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', # 'django.contrib.auth.middleware.AuthenticationMiddleware', # 'django.contrib.messages.middleware.MessageMiddleware', # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
なぜ、CommonMiddleware以外をコメントアウトするかが不明。。。
APIの作成とmigrate
- models.pyにコードを追記
from django.db import models # Create your models here. class Todo(models.Model): text = models.TextField()
- migrateする
python manage.py makemigrations python manage.py sqlmigrate api 0001 python manage.py migrate
今まで、sqmigrate
ってやってなかったんだけで重要ぽいな。。特に初回。
こちらが参考になりました!
【django】マイグレーションツールの使い方 | 遍歴プログラマ日記
シリアライザの作成
モデルをJSONにマッピング(変換)するシリアライザを定義する。
api/serializers.py
from .models import Todo from rest_framework import serializers # serializersをimportする。 # serializersの、HyperlinkedModelSerializerを継承したclassを作成する。 class TodoSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Todo fields = ('id', 'text')
views.pyにて、REST用のビューを作成する。
- api/views.pyを定義する。
from django.shortcuts import render from rest_framework.viewsets import ModelViewSet # ModelViewSetをimportする。 from .models import Todo from .serializers import TodoSerializer # 先ほど定義したTodoSerializerclassを使う。 class TodoViewSet(ModelViewSet): queryset = Todo.objects.all()#querysetは、Todo.objectsのインスタンス serializer_class = TodoSerializer#serializer_classを定義する。
- ModelViewSetは、
A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create().
とのこと。つまり、listとかcreateとかのアクションを持つCBVのことらしい。(get, postは無いので、フォームはできないのかな。)参照サイトは以下の通り。
Viewsets - Django REST framework
APIルーティング
- APIを処理できるようにルーティングの設定をする。ルーティングというのは、多分urlのルートを設定するということかな。urls.pyを修正する。
from django.conf.urls import url, include #includeを追記 from rest_framework.routers import DefaultRouter from api import views # apiappのviewsをimportする。 from django.contrib import admin router = DefaultRouter()#DefaultRouter classのインスタンスをrouterに代入する。 router.register(r'todos', views.TodoViewSet)#これは、todos/に、views.TodoViewSetをルートするという意味だと思う。 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include(router.urls)),#router.urlsをincludeする。 url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),#api-authには、rest_framework.urlsをincludeする。 ]
これはちょっとコツをつかむまで時間かかりそうやな.
- routingは、rest_frameworkの、routersの、DefaultRouter classなどを利用する。
- routerなどのような変数に、DefaultRouter()のインスタンスを代入して、それを使ってurlを設定する。
- DefaultRouter().registerメソッドで、url名と、viewを定義する。これにより、DefaultRouter().urlsに、registerメソッドで定義されたルートが定義される。
- DefaultRouter().urlsをincludeすることで、djangoとapiのルーティングが可能になる。
フロントエンドの作成~静的ファイルの設定
- setting.pyに追記する。
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
- static ディレクトリを作成する。
mkdir static
HTMLファイルを作成する。
- 多分、これはangular1 + bootstrap で書かれてると思う。
<!doctype html> <html ng-app="djangoTodo"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Django REST framework Todo App</title> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <style> html { overflow-y:scroll; } body { padding-top:50px; } #todo-list { margin-bottom:30px; } </style> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script> <script src="core.js"></script> </head> <body ng-controller="mainController"> <div class="container"> <div class="jumbotron text-center"> <h1>Todoリスト <span class="label label-info">{{ todos.length }}</span></h1> </div> <div id="todo-list" class="row"> <div class="col-sm-4 col-sm-offset-4"> <div class="checkbox" ng-repeat="todo in todos"> <label> <input type="checkbox" ng-click="deleteTodo(todo.id)"> {{ todo.text }} </label> </div> </div> </div> <div id="todo-form" class="row"> <div class="col-sm-8 col-sm-offset-2 text-center"> <form> <div class="form-group"> <input type="text" class="form-control input-lg text-center" placeholder="Todoを入力してください" ng-model="formData.text"> </div> <button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">追加</button> </form> </div> </div> </div> </body> </html>
JSファイルを作成する。
var djangoTodo = angular.module('djangoTodo', []); function mainController($scope, $http) { $scope.readTodos = function() { $http.get('/api/todos/') //ここで、todosのviewにアクセスしてdjagnorestframeworkで読み込む。 .success(function(data) { $scope.formData = {}; $scope.todos = data; console.log(data); }) .error(function(data) { console.log('Error: ' + data); }); }; $scope.createTodo = function() { $http.post('/api/todos/', $scope.formData)//ここで、todosのviewにアクセスしてdjagnorestframeworkを通じて追加する。 .success(function(data) { console.log(data); $scope.readTodos(); }) .error(function(data) { console.log('Error: ' + data); }); }; $scope.deleteTodo = function(id) { $http.delete('/api/todos/' + id + '/')//ここで、todosのviewにアクセスしてdjagnorestframeworkを通じて削除する。 .success(function(data) { console.log(data); $scope.readTodos(); }) .error(function(data) { console.log('Error: ' + data); }); }; $scope.readTodos(); }
リダイレクトさせる。
- index.htmlにリダイレクトするように設定する。これは地味に重要だな!これでajaxのtodoリストが可能になるのか!すごい!
from django.conf.urls import url, include #includeを追記 from django.views.generic import RedirectView from rest_framework.routers import DefaultRouter from api import views # apiappのviewsをimportする。 from django.contrib import admin router = DefaultRouter()#DefaultRouter classのインスタンスをrouterに代入する。 router.register(r'todos', views.TodoViewSet)#これは、todos/に、views.TodoViewSetをルートするという意味だと思う。 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include(router.urls)),#router.urlsをincludeする。 url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),#api-authには、rest_framework.urlsをincludeする。 url(r'^todo/', RedirectView.as_view(url='/static/index.html')), ]
なるほど!!これは便利やな!!後何個かやってみよう。 angularすごいな!