LoginSignup
0
0

More than 1 year has passed since last update.

【Django REST Framework】外部APIのデータをお気に入りに登録したい

Last updated at Posted at 2022-01-10

外部APIのデータをお気に入りしていく機能を実装したいと思います。
一応実装できたかなというくらいで、もっと良い書き方があるかもしれませんが、そこは勉強中なのでご容赦ください。。。

前回書いた記事同様、Finaicial Modeling Prepを使用していきます。
【Django REST Framework】外部APIをAPIViewで取得する

1.モデルの作成

models.py
from django.conf import settings

class FavoStock(TimeStampModel):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='favorites')
    symbol = models.CharField(max_length=20, blank=False)
    isin = models.CharField(max_length=12, blank=True)
    vender = models.CharField(max_length=10, blank=True)
    description = models.CharField(max_length=100, blank=False)

    def __str__(self):
        return f"{self.profile.user.username} likes {self.symbol}"

本来のお気に入り機能であれば、ForeignKeyFieldやManyToManyFieldで対象のモデルと接続するんでしょうが、今回はデータベースに銘柄リストを登録していないため、普通の登録・削除の機能に近いです。

2.シリアライザの作成

models.py
from rest_framework import serializers
from profiles.models import Profile, FavoStock


class FavoStockSerializer(serializers.ModelSerializer):
    profile = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = FavoStock
        exclude = ('updated_at', )

3.ビューの作成

views.py
class FavoStockListAPIView(mixins.ListModelMixin,
                           generics.GenericAPIView):
    serializer_class = FavoStockSerializer
    permission_classes = [IsAuthenticated, ]

    def get_queryset(self):
        queryset = FavoStock.objects.all()
        request_uuid = self.kwargs.get('uuid')
        return queryset.filter(profile__uuid=request_uuid).order_by('-created_at')

    def get(self, request, uuid):
        return self.list(request)


class FavoStockCreateAPIView(generics.CreateAPIView):
    queryset = FavoStock.objects.all()
    serializer_class = FavoStockSerializer
    permission_classes = [IsAuthenticated, IsOwnFavoStockOrReadOnly]

    def perform_create(self, serializer):
        symbol = self.request.data.get('symbol')
        user_profile = self.request.user.profile
        queryset = self.get_queryset()

        has_user_added = self.queryset.filter(symbol=symbol, profile=user_profile).exists()

        if has_user_added:
            raise ValidationError('already added.')

        serializer.save(profile=user_profile)


class FavoStockDestroyAPIView(generics.DestroyAPIView):
    queryset = FavoStock.objects.all()
    serializer_class = FavoStockSerializer
    permission_classes = [IsAuthenticated, IsOwnFavoStockOrReadOnly]
    lookup_field ='symbol'

    def perform_destroy(self, instance):
        symbol = self.kwargs.get('symbol')
        user_profile = self.request.user.profile
        queryset = self.get_queryset()

        has_user_added = self.queryset.filter(symbol=symbol, profile=user_profile).exists()

        if not has_user_added:
            raise ValidationError('not exists.')

        instance.delete()

ここはもう少し短くできるだろうなとモヤモヤしています。

ListViewではプロファイルのuuidをパラメータとして渡すことで、そこ人のお気に入り一覧を見ることができます。

Create、Destroyでは自分が登録したレコード以外は操作できないようにしています。
重複などを避けるためにhas_user_addedでレコードのチェックを行っています。

4.URLの設定

urls.py
    path('addfavorite/', FavoStockCreateAPIView.as_view(), name="add-favorite"),
    path('removefavorite/<str:symbol>/', FavoStockDestroyAPIView.as_view(), name='remove-favorite'),

上記をurlpatternsに追加しました。

(メモ:permissions.py)

permissions.py
class IsOwnFavoStockOrReadOnly(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.profile == request.user.profile

結果

↓リスト
image.png

↓登録成功
image.png

↓登録失敗(すでに登録済み)
image.png

まとめ

とりあえず実装できました。
FavoStockモデルはProfileアプリの中にある一方で、株式の情報取得は別のアプリで行っているなど、まだまだ理解ができていないところが多いですが、少しづつ勉強していきます。

(なんでFavoStockって中途半端な名前にしたんだろう…)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0