Relationships & Hyperlinked APIs
https://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/
对于表之间的关联关系, ModelSerializer 默认是使用 外键 的ID 作为序列化返回值的。
但是 对于web应用来说, 其更想知道 API形式的URL.
At the moment relationships within our API are represented by using primary keys. In this part of the tutorial we'll improve the cohesion and discoverability of our API, by instead using hyperlinking for relationships.
使用此类后, 会新增一个 url field, 此结果序列化后, 就是url
class SnippetSerializer(serializers.HyperlinkedModelSerializer): owner = serializers.ReadOnlyField(source='owner.username') highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html') class Meta: model = Snippet fields = ['url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style'] class UserSerializer(serializers.HyperlinkedModelSerializer): snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True) class Meta: model = User fields = ['url', 'id', 'username', 'snippets']
每一个path都定义了name, 便于进行反向查询。
from django.urls import path from rest_framework.urlpatterns import format_suffix_patterns from snippets import views # API endpoints urlpatterns = format_suffix_patterns([ path('', views.api_root), path('snippets/', views.SnippetList.as_view(), name='snippet-list'), path('snippets/<int:pk>/', views.SnippetDetail.as_view(), name='snippet-detail'), path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view(), name='snippet-highlight'), path('users/', views.UserList.as_view(), name='user-list'), path('users/<int:pk>/', views.UserDetail.as_view(), name='user-detail') ])
通过reverse 接口, 查询出完整的url返回给客户端。
from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.reverse import reverse @api_view(['GET']) def api_root(request, format=None): return Response({ 'users': reverse('user-list', request=request, format=format), 'snippets': reverse('snippet-list', request=request, format=format) })
reverse
https://docs.djangoproject.com/en/3.2/ref/urlresolvers/#django.urls.reverse
django.urls
utility functions¶
reverse()
¶If you need to use something similar to the
url
template tag in your code, Django provides the following function:
reverse
(viewname, urlconf=None, args=None, kwargs=None, current_app=None)¶
viewname
can be a URL pattern name or the callable view object. For example, given the followingurl
:from news import views path('archive/', views.archive, name='news-archive')
you can use any of the following to reverse the URL:
# using the named URL reverse('news-archive') # passing a callable object # (This is discouraged because you can't reverse namespaced views this way.) from news import views reverse(views.archive)