【Django REST Framework】外部APIをAPIViewで取得する

Django REST FrameworkのAPIViewを使って外部APIを呼び出してみます。
今回はFinancial Modeling PrepをのSearchAPI（株式のシンボルを探すAPI）を使用しています。

＜環境変数＞
.env ⇒ settings.py ⇒ モジュール

##1.モジュールの作成
```python:プロジェクト/lib/fmp_api.py
from django.conf import settings
import requests

API_KEY = settings.FMP_API_KEY
FMP_V3 = settings.FMP_V3

def search_symbol(keyword, limit=10, exchange=None):
    url = FMP_V3 + 'search'
    query = {
        'query': keyword,
        'limit': limit,
        'apikey': API_KEY
    }
    if exchange:
        query['exchange'] = exchange
    r = requests.get(url, params=query, timeout=2.0)
    if r.status_code == 200:
        data = r.json()
        return data
    else:
        return None
```

キーワードを指定すると10個のシンボルが返ってきます。
取引所の指定をする場合はexchangeを指定します。

##2.シリアライザの作成
```python:アプリ/api/v1/views.py
from rest_framework import serializers

from profiles.models import FavoStock


class FMPSearchSymbolSerializer(serializers.Serializer):
    symbol = serializers.CharField(max_length=20)
    name = serializers.CharField(max_length=100)
    currency = serializers.CharField(max_length=3)
    stockExchange = serializers.CharField(max_length=100)
    exchangeShortName = serializers.CharField(max_length=15)
    user_has_liked_symbol = serializers.SerializerMethodField()

    def get_user_has_liked_symbol(self, instance):
        request = self.context.get('request')
        return FavoStock.objects.filter(profile=request.user.profile, symbol=instance['symbol']).exists()

```

お気に入りは別アプリのモデルからインポート。
登録があればtrue、なければfalseで返ってきます。

##3.クラスベースビューの作成
```python:アプリ/api/v1/views.py
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response

from プロジェクト名.lib import fmp_api
from stocks.api.v1.serializers import FMPSearchSymbolSerializer

class SearchFMPSymbolAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request,kw):
        data = fmp_api.search_symbol(kw)
        if data:
            results = FMPSearchSymbolSerializer(data, many=True, context={"request": request})
            return Response(results.data)
        else:
            return Response(
                {
                    "error": {
                        "code": 404,
                        "message": "not found"
                    }
                },
                status = status.HTTP_404_NOT_FOUND
            )
```

日本語で探すとnot foundでレスポンスされます。

##4.URLの設定
```python:アプリ/api/v1/urls.py
from django.urls import path, include
from stocks.api.v1.views import SearchFMPSymbolAPIView

urlpatterns = [
    path('search/<str:kw>/', SearchFMPSymbolAPIView.as_view(), name='search-symbol'),
]
```

あとはプロジェクトのurls.pyにアプリのurlsを追加して終了です。

##結果
結果が出力される場合↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182517/acc675ca-42a0-85e8-0a09-96e4fe7f8a7b.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182517/d8bf3e7c-86c1-96b5-6283-e4e2db408860.png)


エラーの場合↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182517/6f96a357-ff63-abde-c3fb-f70a12f48402.png)


#参考
[DjangoでAPI呼び出し](https://qiita.com/egplnt/items/9cc0dec14d1b3eb7e34c)
[Django rest framework & external api](https://stackoverflow.com/questions/48435487/django-rest-framework-external-api)