本シリーズのトップページ |
---|
https://qiita.com/robozushi10/items/4559a281d0319eb62c6c |
はじめに
CI による自動テストの中で、テスト結果の証拠としてキャプチャした画像(PNG)を
REST POST を使って WEBアプリに画像を Upload する機構を作成したときの抜粋である.
ファイル構成
ここでは、次のようなファイル構成で記述している.
home
|-- foo
|-- mysite ................... Django プロジェクト
|-- myapp ................ Django アプリ
| |-- models.py
| 略
|-- apiv1 ................ DRF
| |-- serializers.py
| |-- views.py
| |-- urls.py
略
|-- config
|-- settings.py
|-- urls.py
|-- wsgi.py
略
myapp/models.py
次の点に留意して、モデル「XXXX
」を実装する.
-
imgfile = models.ImageField(upload_to=メソッド)
を定義する. (下記💥) -
上記
upload_to
で指定されたメソッドを XXXX クラス内で実装する (下記🛑) -
フィールド「
imgfile
」(下記💥) に設定された値が、
get_upload_path
関数(下記🛑) の引数filename
に設定されている. -
get_upload_path
関数内(下記🛑)で「XXXX
」クラスの
「restkey」「scenario」「testcase」を組み合わせて Upload 先のパスを組み立てている.
class XXXX(models.Model):
""" テスト結果保持 TBL """
def 🛑get_upload_path(self, filename):
k = self.restkey
s = self.scenario if self.scenario else 'scenario'
t = self.testcase if self.testcase else 'testcase'
return '/'.join(['./images', k, s, t, filename])
restkey = models.CharField(verbose_name='RESTful APIキー', max_length=64)
scenario = models.CharField(verbose_name='シナリオ名', null=True, blank=True, max_length=40)
testcase = models.CharField(verbose_name='テストケース名', null=True, blank=True, max_length=64)
💥imgfile = models.ImageField(upload_to=🛑get_upload_path, null=True, blank=True)
apiv1/serializers.py
上記モデル「XXXX」に対する DRF シリアライザである.
「XXXX」クラスの「imgfile
」のみ、別途serializers.ImageField()
を使って定義する.(下記💚)
from rest_framework import serializers
from XXXX.models import *
class XXXXSerializer(serializers.ModelSerializer):
""" テスト結果保持 TBL """
imgfile = serializers.ImageField(use_url=True) 💚
class Meta:
model = XXXX
fields = '__all__'
参考にした記事
内容 | URL |
---|---|
REST によるファイルのアップロード方法 | https://stackoverflow.com/questions/45559471/django-rest-framework-upload-image-api |
config/urls.py
ルーティングを定義する.
エンドポイントとして「api/v1/
」が指定された場合は、
後述のapi/v1/urls.py
でルーティングさせる.
from django.contrib import admin
from django.urls import path
from django.urls import include
from django.conf.urls import url, include
from django.views.generic import TemplateView
from django.views.generic import RedirectView
from apiv2 import views
urlpatterns = [
path('api/v1/', include('apiv1.urls')),
]
apiv1/urls.py
DRF に関するルーティングを定義する.
下記🏷️と📛の詳細については後述している.
from django.urls import path, include
from rest_framework import routers
from . import views
urlpatterns = [
path('', include(router.urls)),
path('myapp/XXXX/', 🏷️views.XXXXListCreateAPIView.as_view()),
path('myapp/XXXX/<pk>/', 📛views.XXXXRetrieveUpdateDestroyAPIView.as_view()),
]
apiv1/views.py
前述の 🏷️ と 📛 のクラスの実装である.
次の 🏷️ と 📛 のクラスに対して、それぞれ次の 1行以外を追加した以外は特殊な記述は無い (はず)
・parser_classes = (MultiPartParser, FormParser) #! 🎰引用
from rest_framework import generics
from rest_framework import status
from rest_framework import views #! 📘引用
from django.shortcuts import get_object_or_404 #! 📘引用
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser #! 🎰引用
from rest_framework.generics import ListAPIView
from myapp.models import *
from .serializers import *
class XXXXListCreateAPIView(views.APIView):🏷️
""" XXXX の取得(一覧)・登録 API クラス """
parser_classes = (MultiPartParser, FormParser) #! 🎰引用
def get(self, request, *args, **kwargs):
l = XXXX.objects.all()
ser = XXXXSerializer(instance=l, many=True)
return Response(ser.data, status.HTTP_200_OK)
def post(self, request, *args, **kwargs):
ser = XXXXSerializer(data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
return Response(ser.data, status.HTTP_201_CREATED)
class XXXXRetrieveUpdateDestroyAPIView(views.APIView):
""" XXXX の取得(詳細)・更新・一部更新・削除 API クラス """
parser_classes = (MultiPartParser, FormParser) #! 🎰引用
def get(self, request, pk, *args, **kwargs):
oc = get_object_or_404(XXXX, pk=pk)
ser = XXXXSerializer(instance=oc)
return Response(ser.data, status.HTTP_200_OK)
def put(self, request, pk, *args, **kwargs):
oc = get_object_or_404(XXXX, pk=pk)
ser = XXXXSerializer(instance=oc, data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
return Response(ser.data, status.HTTP_200_OK)
def patch(self, request, pk, *args, **kwargs):
oc = get_object_or_404(XXXX, pk=pk)
ser = XXXXSerializer(instance=oc, data=request.data, partial=True)
ser.is_valid(raise_exception=True)
ser.save()
return Response(ser.data, status.HTTP_200_OK)
def delete(self, request, pk, *args, **kwargs):
oc = get_object_or_404(XXXX, pk=pk)
ser.delete()
return Response(status.HTTP_204_NO_CONTENT)
参考にした記事
内容 | URL | 備考 |
---|---|---|
APIView のために必要 | 現場で使える Django REST Framework の教科書 (Django の教科書シリーズ) | 上記📘 |
REST によるファイルのアップロード方法 | https://stackoverflow.com/questions/45559471/django-rest-framework-upload-image-api | 上記🎰 |
以上.