仮想サーファーの波乗り

仮想サーファーの日常

プログラミング・SNS分析・自動化などに関してよく書く雑記ブログ

Django REST frameworkでPrimary Key(主キー)以外でURL指定する


f:id:virtual-surfer:20190404195830p:plain

Django REST frameworkを使って簡単にAPIを実装したる!と思っていましたが、結構つまる...。

今回は、APIのURLでPrimary Key(主キー)以外でデータを取得できるようにする方法が分からず、実装まで時間がかかったのでまとめておきます。


実現したいこと

下の画像のようにPrimary Keyではない値(ここではPrimary Keyになっている「id」ではなくて、「account_name」)でURL指定してデータを取得したい。

f:id:virtual-surfer:20190404193851p:plain


実装方法メモ

まずは元々の実装の状態。

元々の実装の状態


各種バージョンは以下。

・Django : 2.0.6
・Python : 3.6.4
・djangorestframework : 3.8.2


ModelとViewとSerializerとurlの初期状態は以下のようなものでした。

models.py

from django.db import models

class User(models.Model):
    user_name = models.CharField(max_length=128)
    account_name = models.CharField(max_length=128, unique=True, db_index=True)
    description = models.TextField(max_length=512, null=True)
    profile_image_link = models.ImageField(unique=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.user_name

views.py

from rest_framework import generics

from .models import User
from .serializers import UserSerializer

class User(generics.RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

serializer.py

from rest_framework import serializers
from .models import User

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'user_name', 'account_name', 'description', 'profile_image_link')

urls.py

from django.urls import path

from .views import User

urlpatterns = [
    path('user/<int:pk>/', User.as_view()),
]


この状態でuserのデータを取得しようとすると、Primary Key指定でデータを取得することができる。

f:id:virtual-surfer:20190404194722p:plain


しかしこの実装のままaccount_nameでURL指定してデータ取得しようとすると、もちろんそんなidデータはなくてエラーになる。

f:id:virtual-surfer:20190404194905p:plain


解決できた方法

解決できた実装をメモしておきます。Viewとurlだけ変更すればOKでした( ・v・)b

models.py →修正なし

views.py

from rest_framework import generics

from .models import User
from .serializers import UserSerializer

class User(generics.RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'account_name' #ここ追加する

serializer.py →修正なし

urls.py

from django.urls import path

from .views import User

urlpatterns = [
    # path('user/<int:pk>/', User.as_view()), ←消す
    path('user/<str:account_name>/', User.as_view(), name='account_name'), #ここ追加する
]

URLで「account_name」という変数を受け取るよということを明示し、Viewで「account_name」でデータを絞り込みするよということを明示。


これで「http://localhost:8000/api/user/virtual_techX/」にアクセスすると...

f:id:virtual-surfer:20190404193851p:plain

「account_name」指定でデータが取得できていますね!よかったよかった( ´ v ` )


まとめ

以上、「Django REST frameworkでPrimary Key(主キー)以外でURL指定する」でした!

知ってしまえば簡単だけど、一度も実装したことないと無限に時間かかるつらみ...。


一応公式のドキュメントリンクも貼っておきます。

Home - Django REST framework


では!