Django-rest-framework勉強中です
準備
前回と同じですが、一応Model構成載せておきます。
from django.db import models
DISTRICT_CATEGORIES = [
(1, "地区1"),
(2, "地区2"),
(3, "地区3"),
(4, "地区4"),
]
class Student(models.Model):
"""生徒情報"""
# 生徒ID
student_id = models.CharField(max_length=4, primary_key=True)
# クラス
class_no = models.CharField(max_length=1)
# 出席番号
attendance_no = models.IntegerField()
# 名前
name = models.CharField(max_length=20)
# 地区番号
district_no = models.CharField(max_length=1, choices=DISTRICT_CATEGORIES)
# フリーコメント
comment = models.CharField(max_length=200,blank=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["class_no", "attendance_no"],
name="class_attendance_unique"
),
]
STUDENT ID | CLASS NO | ATTENDANCE NO | NAME | DISTRICT NO | COMMENT |
---|---|---|---|---|---|
0005 | 2 | 2 | fugafuga | 地区1 | 2組2番 |
0004 | 2 | 1 | hogehoge | 地区2 | 2組1番 |
0003 | 1 | 3 | 山田3番 | 地区4 | 1組3番 |
0002 | 1 | 2 | 山田花子 | 地区2 | 1組2番 |
0001 | 1 | 1 | 山田太郎 | 地区1 | 1組1番 |
post
今回はpostです。リソースの登録をする役割のあるメソッドですが、実際の運用ではもうちょっといろいろなことをやらせるAPIを準備しなくてはならないのかなと思います。
一旦はリソースの登録をするAPIを作成してみます。
レコードの新規作成
restの原則では、postはリソースの作成(CRUDで言うC)を行い、冪等性は保証しません。まぁ、今回はあまり気にせずDRFの書き方みたいな感じで軽く書いてみようかなと思います。
serializer
まぁ、getのときと一緒です。
ModelSerializerを継承して、studentモデルの全カラムを作成しにいきます。
from rest_framework import serializers
from ..models import Student
class StudentSerializer(serializers.ModelSerializer):
"""Studentクラスのシリアライザ"""
class Meta:
model = Student
fields = '__all__'
view
簡単に書いています。実際の業務だともうちょい複雑なコードになるかもです。
リクエストをデシリアライズした後、serializer.is_valid()
というメソッドを呼んでいます。一度バリデーションを通さないと次のserializer.save()
が呼べないことになっています。validationの内容は、デフォルトではModelSerializerであればModelの定義に即しているかのみのチェックです。
例えば生徒情報IDというフィールドでは、
student_id = models.CharField(max_length=4, primary_key=True)
このようにModelを定義しているので、max_lengthが4文字かどうかなどのチェックがかかるということがわかります。
そしてその後の.save()
で、SQLのcreate文が流れるという感じです。
from rest_framework.response import Response
from rest_framework.views import APIView
from ..serializers.student_create import StudentSerializer
class StudentCreateAPIView(APIView):
"""
生徒情報新規登録API
"""
def post(self, request, *args, **kwargs):
# リクエストをシリアライズ
serializer = StudentSerializer(data=request.data)
# リクエストのバリデーション
serializer.is_valid(raise_exception=True)
# リソースの新規作成(create)
serializer.save()
# レスポンス
return Response({'result':True})
url
pkはパスパラメータでなくbodyに入れることとしています。
from django.urls import path
from . import views
urlpatterns = [
# path('<pk>/retrieve/', views.StudentRetrieveAPIView.as_view())
# path('<class_no>/<int:attendance_no>/retrieve/', views.StudentRetrieveAPIView.as_view()),
path('create/', views.StudentCreateAPIView.as_view())
]
いざ実行
import requests
student_id='0006'
class_no='1'
attendance_no=4
name="黒崎一護"
district_no='4'
comment='尸魂界'
body = {
'student_id':student_id,
'class_no':class_no,
'attendance_no':attendance_no,
'name':name,
'district_no':district_no,
'comment':comment,
}
response = requests.post('http://127.0.0.1:8000/student/create/', body)
print(response.text) # レスポンスのHTMLを文字列で取得
一意制約に気をつけて実行したところ、viewで定義したとおりresult:true
が返ってきました。
そして以下のレコードができていました!!
STUDENT ID | CLASS NO | ATTENDANCE NO | NAME | DISTRICT NO | COMMENT |
---|---|---|---|---|---|
0006 | 1 | 4 | 黒崎一護 | 地区4 | 尸魂界 |
ちなみに・・・
validationに引っかかると、以下のようにエラーで教えてくれます。
student_id='00007'
でリクエストすると、以下エラーとなります。
rest_framework.exceptions.ValidationError: {'student_id': [ErrorDetail(string='この項目が4文字より長くならないようにしてください。', code='max_length')]}
汎用APIViewも使ってみたい
views.pyを以下のように変えてみました。
from rest_framework import generics
from ..models import Student
from ..serializers import StudentSerializer
class StudentCreateAPIView(generics.CreateAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
実行
import requests
student_id='0007'
class_no='1'
attendance_no=5
name="朽木ルキア"
district_no='4'
comment='袖白雪'
body = {
'student_id':student_id,
'class_no':class_no,
'attendance_no':attendance_no,
'name':name,
'district_no':district_no,
'comment':comment,
}
# response = requests.get('http://127.0.0.1:8000/student/{}/retrieve/'.format(id))
response = requests.post('http://127.0.0.1:8000/student/create/', body)
print(response.text) # レスポンスのHTMLを文字列で取得
できちゃった・・・。
STUDENT ID | CLASS NO | ATTENDANCE NO | NAME | DISTRICT NO | COMMENT |
---|---|---|---|---|---|
0007 | 1 | 5 | 朽木ルキア | 地区4 | 袖白雪 |
本当にコード量が少ないですね・・・。
ひとまず、postリクエストでリソースの新規作成ができました。
次はリソースの一部更新(patch? put?) をして基礎編は終了したいと思います。