序列化器: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_namelookup_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')
上一篇下一篇

猜你喜欢

热点阅读