現在Django及びdjango-rest-frameworkを用いて、REST APIを作成しています。目標は以下のようなURL構造を持つAPIを作ることです。
users(全ユーザ取得)
users/1(ユーザ詳細取得)
users/1/posts(投稿全件取得)
users/1/posts/1(投稿詳細取得)
現在のところ、usersは全ユーザ、users/1はユーザ詳細の情報をしっかり返してくれます。一方、users/1/postsやusers/1/post1/1はエラーが返ってきてしまいます。
具体的なエラー内容としては、
ーusers/1/postsにアクセス
name 'Response' is not defined
Exception Location: /Users//Desktop//django_project/api/views.py in list, line 26
ーusers/1/posts/1にアクセス
name 'Response' is not defined
Exception Location: /Users//Desktop//django_project/api/views.py in retrieve, line 31
【serializers.pyを変更後(こちらの解決方法の提示をよろしくおねがいします。)】
Could not resolve URL for hyperlinked relationship using view name "post-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field
attribute on this field.
どうやらapi/views.py のPostView内で発生しているようです。
公式のdjango rest frameworkのサイトを見る限り、Responseはimportせずとも使えるようですが、エラーが出てしまいます。
どなたか分かる方、ぜひお力添えをお願いいたします。
[作成の際に参考にさせていただいた記事一覧]
ーREST APIを作る際
https://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8
ーネストされたルート作成の際
https://qiita.com/hfujima/items/fe8d4470a05895a70748
https://github.com/alanjds/drf-nested-routers/blob/master/README.md
python
1#api/views.py 2 3from django.shortcuts import render 4from rest_framework import viewsets 5from .models import User, Friend, Post 6from .serializers import UserSerializer, FriendSerializer, PostSerializer 7 8from rest_framework.generics import get_object_or_404 9 10 11class UserView(viewsets.ModelViewSet): 12 queryset = User.objects.all() 13 serializer_class = UserSerializer 14 15 16class FriendView(viewsets.ModelViewSet): 17 queryset = Friend.objects.all() 18 serializer_class = FriendSerializer 19 20 21class PostView(viewsets.ModelViewSet): 22 queryset = Post.objects.all() 23 serializer_class = PostSerializer 24 25 def list(self, request, user_pk=None): 26 posts = self.queryset.filter(author=user_pk) 27 serializer = self.get_serializer(posts, many=True) 28 return Response(serializer.data) 29 30 def retrieve(self, request, pk=None, user_pk=None): 31 post = self.queryset.get(pk=pk, author=user_pk) 32 serilaizer = self.get_serializer(post, many=True) 33 return Response(serializer.data) 34
python
1#api/models.py 2 3from django.db import models 4from django.core.validators import MaxValueValidator, MinValueValidator 5 6class User(models.Model): 7 username = models.CharField(max_length=20) 8 email = models.EmailField() 9 password = models.CharField(max_length=20) 10 11 def __str__(self): 12 return self.username 13 14class Friend(models.Model): 15 owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owner') 16 friend = models.ForeignKey(User, on_delete=models.CASCADE, related_name='friend') 17 18 def __str__(self): 19 return self.friend 20 21 22class Post(models.Model): 23 CATEGORY_CHOICES = [ 24 ('JPN', '和食'), 25 ('LOCAL', '郷土料理'), 26 ('SUSHI', '寿司'), 27 ('RAMEN', 'ラーメン類'), 28 ('CURRY', 'カレー'), 29 ('FA', 'ファミレス・ファストフード'), 30 ('MEAT', '焼肉・ステーキ等の肉関連'), 31 ('BAR', '居酒屋・バー'), 32 ('CHN', '中華'), 33 ('WES', '洋食'), 34 ('ITA', 'イタリアン'), 35 ('FRA', 'フレンチ'), 36 ('ASIA', 'アジア・エスニック'), 37 ('CAFE', 'カフェ'), 38 ('SWEETS', 'スイーツ'), 39 ('OTHER', 'その他'), 40 ] 41 42 author = models.ForeignKey(User, on_delete=models.CASCADE) 43 created_at = models.DateTimeField(auto_now_add=True) 44 updated_at = models.DateTimeField(auto_now=True) 45 name = models.CharField(max_length=50) 46 area = models.CharField(max_length=50) 47 address = models.CharField(max_length=50, blank=True) 48 dish = models.CharField(max_length=100, blank=True) 49 category = models.CharField( 50 max_length=20, 51 choices=CATEGORY_CHOICES 52 ) 53 expense = models.IntegerField(blank=True) 54 note = models.TextField(blank=True) 55 img = models.ImageField( 56 blank=True, 57 upload_to='post_image' 58 ) 59 rating = models.IntegerField( 60 validators=[ 61 MinValueValidator(1), 62 MaxValueValidator(5) 63 ] 64 ) 65 66 def __str__(self): 67 return self.name 68
python
1#api/serializers.py 2 3from rest_framework import serializers 4from .models import User, Friend, Post 5 6class UserSerializer(serializers.HyperlinkedModelSerializer): 7 posts = serializers.HyperlinkedRelatedField( 8 many=True, read_only=True, view_name="post-detail", lookup_url_kwarg="post_id" 9 ) 10 11 class Meta: 12 model = User 13 fields = ( 14 'id', 15 'url', 16 'username', 17 'email', 18 'password', 19 ) 20 read_only_fields = "posts" 21 22 23class FriendSerializer(serializers.HyperlinkedModelSerializer): 24 class Meta: 25 model = Friend 26 fields = ( 27 'owner', 28 'friend' 29 ) 30 31class PostSerializer(serializers.HyperlinkedModelSerializer): 32 category = serializers.CharField(source='get_category_display') 33 author = UserSerializer() 34 class Meta: 35 model = Post 36 fields = ( 37 'id', 38 'url', 39 'author', 40 'created_at', 41 'updated_at', 42 'name', 43 'area', 44 'address', 45 'dish', 46 'category', 47 'expense', 48 'note', 49 'img', 50 'rating' 51 ) 52
python
1#api/urls.py 2 3from django.urls import path, include 4from .views import UserView, FriendView, PostView 5from rest_framework_nested import routers 6 7router = routers.SimpleRouter() 8router.register("users", UserView) 9 10users_router = routers.NestedSimpleRouter(router, "users", lookup="user") 11users_router.register("posts", PostView) 12 13router.register("friends", FriendView) 14 15 16urlpatterns = [path("", include(router.urls)), path("", include(users_router.urls))] 17
python
1#django_project/urls.py 2 3from django.conf import settings 4from django.conf.urls.static import static 5from django.contrib import admin 6from django.urls import path, include 7 8urlpatterns = [ 9 path('admin/', admin.site.urls), 10 path('api/', include('comida_api.urls')) 11] 12 13urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 14