序列化关系

建表

class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    duration = models.IntegerField()

    class Meta:
        unique_together = ['album', 'order']
        ordering = ['order']

    def __str__(self):
        return '%d: %s' % (self.order, self.title)

一、字符串相关领域

StringRelatedField可以使用其方法表示关系的目标。__str__

class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.StringRelatedField(many=True)          # 此字段只读     参数many:如果应用于多人关系,应该将此参数设置为True

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

将会序列化为以下数据结构表示

{
    'album_name': 'Things We Lost In The Fire',
    'artist': 'Low',
    'tracks': [
        '1: Sunflower',     # order:title
        '2: Whitetail',
        '3: Dinosaur Act',
        ...
    ]
}

二、主键相关领域

PrimaryKeyRelatedField可以使用其主键表示关系的目标。

序列化器如下

class AlbumSerializer(serializers.ModelSerializer): 
    tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)  #默认情况下,此字段是读写字段,但您可以使用标记更改此行为。read_only

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

参数:
  • queryset- 用于模型实例查找的查询集在验证字段输入时。关系必须明确设置查询集,或设置查询集。read_only=True
  • many- 如果应用于多人关系,您应该将此参数设置为。True
  • allow_null- 如果设置为,字段将接受无效关系的值或空字符串。默认为 。TrueNoneFalse
  • pk_field- 设置为控制主键值的序列化/去除化的字段。例如,将 UUID 主键序列化为其紧凑的六角表示。pk_field=UUIDField(format='hex')

将会序列化为以下数据结构表示

{
    'album_name': 'Undun',
    'artist': 'The Roots',
    'tracks': [
        89,
        90,
        91,
        ...
    ]
}

 三、超链接相关领域

HyperlinkedRelatedField可用于使用超链接表示关系的目标。

序列化器如下

class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='track-detail'
    )                                # 默认情况下,此字段是读写字段,但您可以使用标记更改此行为。read_only

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

注意:
  

  此字段是专为映射到接受单个 URL 关键字参数的 URL 的对象设计的,该参数是使用和参数设置的。lookup_fieldlookup_url_kwarg

  这适用于包含单个主键或作为 URL 一部分的 slug 参数的网址。

  如果您需要更复杂的超链接表示,则需要自定义字段,如下所示自定义超链接字段部分所述。

参数:

  

  • view_name- 应用作关系目标的视图名称。如果您使用的是标准路由器类,这将是一个具有格式的字符串。需要<modelname>-detail
  • queryset- 用于模型实例查找的查询集在验证字段输入时。关系必须明确设置查询集,或设置查询集。read_only=True
  • many- 如果应用于多人关系,您应该将此参数设置为。True
  • allow_null- 如果设置为,字段将接受无效关系的值或空字符串。默认为 。TrueNoneFalse
  • lookup_field-目标上的字段,应用于查找。应对应引用视图上的URL关键字参数。默认值是 。'pk'
  • lookup_url_kwarg-URL配置中定义的关键字参数的名称,该名称对应于查找字段。默认使用与 . 相同的值。lookup_field
  • format- 如果使用格式后缀,超链接字段将使用相同的格式后缀的目标,除非通过使用参数覆盖。format

  


将会序列化为以下数据结构表示

{
    'album_name': 'Graceland',
    'artist': 'Paul Simon',
    'tracks': [
        'http://www.example.com/api/tracks/45/',
        'http://www.example.com/api/tracks/46/',
        'http://www.example.com/api/tracks/47/',
        ...
    ]
}
四、斯卢格相关领域
SlugRelatedField可用于使用目标上的字段表示关系的目标。
序列化器如下
class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='title'
     )    默认情况下,此字段是读写字段,但您可以使用标记更改此行为。read_only    
          用作读写字段时,您通常希望确保 slug 字段与模型字段对应。SlugRelatedFieldunique=True
    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']
参数:
  • slug_field-目标上的字段应用于表示它。这应该是一个能够唯一识别任何给定实例的字段。例如。需要username
  • queryset- 用于模型实例查找的查询集在验证字段输入时。关系必须明确设置查询集,或设置查询集。read_only=True
  • many- 如果应用于多人关系,您应该将此参数设置为。True
  • allow_null- 如果设置为,字段将接受无效关系的值或空字符串。默认为 。TrueNoneFalse

将会序列化为以下数据结构表示

{
    'album_name': 'Dear John',
    'artist': 'Loney Dear',
    'tracks': [
        'Airport Surroundings',
        'Everything Turns to You',
        'I Was Only Going Out',
        ...
    ]
}

五、嵌套关系

这种嵌套关系可以通过使用序列化器作为字段来表示。

如果该字段用于表示对多关系,则应将标志添加到序列化字段中。many=True

序列化器如下

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

将会序列化为以下数据结构表示

>>> album = Album.objects.create(album_name="The Grey Album", artist='Danger Mouse')
>>> Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=245)
<Track: Track object>
>>> Track.objects.create(album=album, order=2, title='What More Can I Say', duration=264)
<Track: Track object>
>>> Track.objects.create(album=album, order=3, title='Encore', duration=159)
<Track: Track object>
>>> serializer = AlbumSerializer(instance=album)
>>> serializer.data
{
    'album_name': 'The Grey Album',
    'artist': 'Danger Mouse',
    'tracks': [
        {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
        {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
        {'order': 3, 'title': 'Encore', 'duration': 159},
        ...
    ],
}

七、可写嵌套序列化器

默认情况下,嵌套序列化器仅读取。如果您想支持将书面操作支持到嵌套序列化字段,则需要创建和/或方法,以便明确指定如何保存儿童关系:create()update()

序列化器如下

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(album=album, **track_data)
        return album

>>> data = {
    'album_name': 'The Grey Album',
    'artist': 'Danger Mouse',
    'tracks': [
        {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
        {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
        {'order': 3, 'title': 'Encore', 'duration': 159},
    ],
}
>>> serializer = AlbumSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.save()
<Album: Album object>

八、自定义关系字段

我们可以定义一个关系字段,以便使用其订购、标题和持续时间将曲目序列化为自定义字符串表示:

import time

class TrackListingField(serializers.RelatedField):
    def to_representation(self, value):
        duration = time.strftime('%M:%S', time.gmtime(value.duration))
        return 'Track %d: %s (%s)' % (value.order, value.name, duration)

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackListingField(many=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

其余关系,官方文档序列化关系 - 詹戈 REST 框架 (django-rest-framework.org)

原文地址:https://www.cnblogs.com/ltyc/p/14894608.html