序列化器:HyperlinkedModelSerializer
2018-05-06 本文已影响966人
SingleDiego
HyperlinkedModelSerializer
类与 ModelSerializer
类相似,只不过它使用超链接来表示关系而不是主键。
默认情况下,序列化器将包含一个 url
字段而不是主键字段。
url
字段将使用 HyperlinkedIdentityField
序列化器字段来表示,并且模型上的任何关系都将使用 HyperlinkedRelatedField
序列化器字段来表示。
我们沿用上一篇的 User 和 Profile 对象关系模型来作为例子:
# models.py
from django.db import models
class Profile(models.Model):
city = models.CharField(max_length=50)
owner = models.OneToOneField('auth.User', related_name='user_profile')
更新我们的序列化器:
# serializers.py
from rest_framework import serializers
from myApp.models import Profile
from django.contrib.auth.models import User
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Profile
# HyperlinkedModelSerializer 会自动生成一个 url 字段来表示超链接
# 我们希望 API 中包括这个字段,所以这里我们在 fields 加上
fields = ('url', 'city', 'owner')
# 我们可以在 extra_kwargs 设置中的 view_name 和 lookup_field
# 来正确配置我们的 URL
# view_name 和 urls.py 中的 name 参数相对应,表示使用哪个 url
# lookup_field 表示用哪个字段来作为 url 的唯一识别标记
# 本例中每个 Profile 的 url 是通过 id 来区分的,所以该字段用 id
extra_kwargs = {
'url': {'view_name': 'profile-detail', 'lookup_field': 'id'},
'owner': {'lookup_field': 'id'}
}
class UserSerializer(serializers.HyperlinkedModelSerializer):
user_profile = ProfileSerializer()
class Meta:
model = User
fields = ('url', 'username', 'email', 'user_profile')
extra_kwargs = {
'url': {'view_name': 'user-detail', 'lookup_field': 'id'},
}
编写 API 视图函数:
# views.py
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from myApp.serializers import ProfileSerializer, UserSerializer
from django.contrib.auth.models import User
from myApp.models import Profile
@api_view(['GET'])
def profile_list(request):
queryset = Profile.objects.all()
# 注意:这里需要带上 context={'request': request}
serializer = ProfileSerializer(queryset, many=True, context={'request': request})
return Response(serializer.data)
@api_view(['GET'])
def profile_detail(request, id):
instance = Profile.objects.get(id=id)
serializer = ProfileSerializer(instance, context={'request': request})
return Response(serializer.data)
@api_view(['GET'])
def user_list(request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True, context={'request': request})
return Response(serializer.data)
@api_view(['GET'])
def user_detail(request, id):
instance = User.objects.get(id=id)
serializer = UserSerializer(instance, context={'request': request})
return Response(serializer.data)
设置 URL:
from django.conf.urls import url
from django.contrib import admin
from myApp.views import profile_list, profile_detail, user_detail, user_list
urlpatterns = [
url(r'^admin/', admin.site.urls),
# name 参数和序列化器的 lookup_field 对应
url(r'^api/profile_list/', profile_list, name='profile-list'),
url(r'^api/profile/(?P<id>[0-9])/$', profile_detail, name='profile-detail'),
url(r'^api/user_list/', user_list, name='user-list'),
url(r'^api/user/(?P<id>[0-9])/$', user_detail, name='user-detail'),
]
现在序列化后的 User 对象是这样的:
{
"url": "http://127.0.0.1:8000/api/user/1/",
"username": "diego",
"email": "",
"user_profile": {
"url": "http://127.0.0.1:8000/api/profile/1/",
"city": "guangzhou",
"owner": "http://127.0.0.1:8000/api/user/1/"
}
}
序列化后的 Profile 对象:
{
"url": "http://127.0.0.1:8000/api/profile/1/",
"city": "guangzhou",
"owner": "http://127.0.0.1:8000/api/user/1/"
}
提示:正确地匹配超链接和 URL conf
有时可能有点困难。打印 HyperlinkedModelSerializer
实例的 repr
是一种特别有用的方法,可以准确检查这些关系预期映射的 view_name
和 lookup_field
。
我们可以显式设置序列化类中的字段。例如:
# serializers.py
from rest_framework import serializers
from myApp.models import Profile
from django.contrib.auth.models import User
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='profile-detail',
lookup_field='id'
)
owner = serializers.HyperlinkedIdentityField(
view_name='user-detail',
lookup_field='id'
)
class Meta:
model = Profile
fields = ( 'url', 'city', 'owner')
class UserSerializer(serializers.HyperlinkedModelSerializer):
user_profile = ProfileSerializer()
url = serializers.HyperlinkedIdentityField(
view_name='user-detail',
lookup_field='id'
)
class Meta:
model = User
fields = ('url', 'username', 'email', 'user_profile')