Django REST Frameworkで画像収集

Django REST Frameworkを使ってapiで画像を収集します。

#1. Django環境を用意します
- [Django Girls Tutorial](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/content/)、[Djangoを使ってみる](https://qiita.com/egplnt/items/9620e1948fedcc052585)等を参照し、Django環境を用意します
- ここでは例として`restfw`というプロジェクトとします

#2. アプリを用意します
- `python manage.py startapp アプリ名`でアプリを用意します。ここではサンプルとして`upload`というアプリを作成しています
- 上記で作成したアプリおよびrest_frameworkを`settings.py`に登録します

```python:restfw/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'upload',
    'rest_framework'
]
```
- `urls.py`に登録します

```python:restfw/urls.py
from django.conf.urls import url, include
from upload.urls import router as upload_router

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^api/', include(upload_router.urls)),]
```
```python:upload/urls.py
from rest_framework import routers
from .views import ImageViewSet


router = routers.DefaultRouter()
router.register(r'images', ImageViewSet)
```

-`models.py`を記述します

```python:upload/models.py
from django.db import models

class Image(models.Model):
    STATUS_DRAFT = "draft"
    STATUS_PUBLIC = "published"
    STATUS_SET = (
            (STATUS_DRAFT, "draft"),
            (STATUS_PUBLIC, "published"),
    )
    filepath = models.CharField(primary_key=True, max_length=1024)
    sender = models.CharField(max_length=32)
    title = models.CharField(max_length=128)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    lat = models.FloatField(default=34.75)
    lng = models.FloatField(default=135.5)
    status = models.CharField(choices=STATUS_SET, default=STATUS_DRAFT, max_length=8)

    def __str__(self):
        return '{}, {}, {}, {}, {}, {}, {}, {}, {}'.format(self.filepath, self.sender, self.title, self.body, self.created_at, self.updated_at, self.lat, self.lng, self.status)
```

- `serializer.py`を記述します

```python:upload/serializer.py
from rest_framework import serializers

from .models import Image

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = ('sender', 'title', 'body', 'created_at', 'updated_at', 'lat', 'lng', 'status')
```

- `views.py`を記述します

```python:upload/views.py
from django.shortcuts import render
import django_filters
from rest_framework import viewsets, filters
from rest_framework.decorators import detail_route, list_route
import os
from rest_framework.response import Response

from .models import Image
from .serializer import ImageSerializer

UPLOAD_DIR = 'static/uploaded_photo/'

class ImageViewSet(viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer

    def create(self, request):
        file = request.FILES['file']
        path = os.path.join(UPLOAD_DIR, file.name)
        destination = open(path, 'wb')
        for chunk in file.chunks():
            destination.write(chunk)
        destination.close()

        if not os.path.exists(path):
            print('File not found:', path)
            return create_render(request)

        image, created = Image.objects.get_or_create(filepath=path)
        if created:
            # image.sender = request.POST['sender']
            image.title = request.POST['title']
            image.body = request.POST['body']
            image.created_at = request.POST['created_at']
            image.updated_at = request.POST['updated_at']
            image.lat = float(request.POST['lat'])
            image.lng = float(request.POST['lng'])
            image.status = request.POST['status']
            image.save()

        return Response({'message': 'OK'})
```

-`static/uploaded_photo`フォルダーを用意します

#3. 試してみます
- [Advanced REST Client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo)を使います
- `Body content type`に`multipart/form-data`を選択して画像を指定してPOSTしてみます

<img width="1680" alt="スクリーンショット 2018-05-09 13.18.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/7a2bc51a-57cc-3987-440f-7d7c1d50e69e.png">

<img width="1680" alt="スクリーンショット 2018-05-09 13.18.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/16a44a7d-2574-ec96-10c4-cfa6a3bc9a45.png">

- `static/uploaded_photo`にアップロードされた画像が保存されていることを確認します

<img width="770" alt="スクリーンショット 2018-05-09 13.35.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/4b8a77f5-d51f-aa4d-6771-412f3455e58a.png">

- `/api`でAPIマネージャーにアクセスできます

<img width="1444" alt="スクリーンショット 2018-05-09 13.51.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/cea056e1-68d9-5322-1d70-7cbe708f5714.png">

<img width="1318" alt="スクリーンショット 2018-05-09 13.51.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/f86101e5-fd0c-61ec-dc27-c7dafef265ea.png">


# 参考
- [Django REST Frameworkを使って爆速でAPIを実装する](https://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8)