Django Rest Framework中文文档:Serializer relations

article/2025/10/12 20:15:47

文章目录

  • 一,django模型间的关系
  • 二,检查序列化器实例详情
  • 三,序列化关系字段
    • (一)StringRelatedField
    • (二)PrimaryKeyRelatedField
    • (三)HyperlinkedRelatedField
    • (四)SlugRelatedField
    • (五)HyperlinkedIdentityField
  • 四,嵌套关系
  • 五,自定义关系字段
  • 六,自定义超链接字段

这是对DRF官方文档:Serializer relations的翻译,根据个人的理解对内容做了些补充、修改和整理。

一,django模型间的关系

在我们对数据进行建模时,最重要的一点就是根据功能需求分析出实体及其关系,

在实现阶段:

  • 一个实体对应一个模型,一个模型就是一张数据表;
  • 实体间的关系由模型中的关系字段进行表示,模型间的关系就是数据表间的关系。

这种设计理念与关系型数据库的设计理念相符。而关系型数据库的强大之就处在于表示与处理各表之间的关联关系。

为此,Django 提供了定义三种最常见的数据库关联关系的方法的关系字段:

  • OneToOneField:一对一关系
  • ForeignKey:多对一关系
  • ManyToManyField:多对多关系

二,检查序列化器实例详情

在使用 Serializer 类创建序列化器类时,对关系进行正确的的表示就非常重要。

而使用 ModelSerializer 类创建序列化器类时,它会自动使用合适的字段处理模型间的关系,检查这些自动生成的字段对于如何确定自定义关系来说是非常有帮助的。

例如查看一个ModelSerializer 子类的实例详情:

>>> from myapp.serializers import AccountSerializer
>>> serializer = AccountSerializer()
>>> print repr(serializer)  # Or `print(repr(serializer))` in Python 3.x.
AccountSerializer():id = IntegerField(label='ID', read_only=True)name = CharField(allow_blank=True, max_length=100, required=False)owner = PrimaryKeyRelatedField(queryset=User.objects.all())

三,序列化关系字段

为了解释各种类型的关系字段,官网的教程为我们提供了一些简单的模型:用于音乐专辑以及其中的歌曲。

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)

模型中只用到多对一关系,Album 是主模型,产生主表,Track 是从模型,产生从表。

(一)StringRelatedField

字段作用:
主模型序列化器中的StringRelatedField字段可以使用从模型中的__str__方法来表示关联关系。

字段参数:

  • many:如果应用于多对一的关系,应该设置为 True。

使用示例:

class AlbumSerializer(serializers.ModelSerializer):tracks = serializers.StringRelatedField(many=True)class Meta:model = Albumfields = ['album_name', 'artist', 'tracks']

效果就是 tracks 属性将使用 Track 模型的 __str__ 方法来产生关联关系,并使用它返回的内容。

将产生以下形式的序列化结果:

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

(二)PrimaryKeyRelatedField

字段作用:
主模型序列化器中的PrimaryKeyRelatedField字段可以使用从模型中的主键字段来表示关联关系。

  • 每个模型必须有一个主键。要么手动使用primary_key=True设置某字段为主键,否则 django 会为表创建名为 id (别名 pk)的自动增长的字段作为主键。参考django doc:Automatic primary key fields

字段参数:

  • queryset:验证字段输入时用于模型实例查找的查询集。关系字段必须显式设置 queryset 或者 read_only=True
  • many:如果应用于多对一的关系,应该设置为 True。
  • allow_null:是否允许该字段接受 None 或为空关系接受空字符串。默认值为 False。
  • pk_field:设置一个字段来控制主键值的序列化/反序列化。

使用示例:

class AlbumSerializer(serializers.ModelSerializer):tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)class Meta:model = Albumfields = ['album_name', 'artist', 'tracks']
  • 默认PrimaryKeyRelatedField字段是可读写的。可以使用read_only标志来更改此行为。

效果就是 tracks 属性将使用 Track 模型的主键即 id (我们没在模型中指定主键)来产生关联关系,并使用主键值。

将产生以下形式的序列化结果:

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

(三)HyperlinkedRelatedField

字段作用:
主模型序列化器中的HyperlinkedRelatedField可以用来表示使用超链接的关系目标。从模型中的主键来表示关联关系。

  • 该字段是为映射到一个URL的对象设计的,该URL接受一个 URL 关键字参数,使用lookup_fieldlookup_url_kwarg参数设置。这适用于URL中包含一个主键或slug参数的URL。如果需要更复杂的超链接表示,则需要自定义字段,请参考自定义超链接字段。

字段参数:

  • view_name:应该用作关系目标的视图名称。如果使用标准的路由器类,则因该是一个格式为 modelname-detail 的字符串。是必要参数
  • queryset:验证字段输入时用于模型实例查找的查询集。关系字段必须显式设置 queryset 或者 read_only=True
  • many:如果应用于多对一的关系,应该设置为 True。
  • allow_null:是否允许该字段接受 None 或为空关系接受空字符串。默认值为 False。
  • lookup_field:应该用于查找的字段。应该对应于被引用视图上的 URL 关键字参数。默认设置是 pk。
  • lookup_url_kwarg:在 URL 配置文件中定义的关键字参数的名称,该参数是应该用于查找字段。默认使用与lookup_field相同的值。
  • format:如果使用格式后缀,超链接字段将为目标使用相同的格式后缀,除非使用format参数重写。

使用示例:

class AlbumSerializer(serializers.ModelSerializer):tracks = serializers.HyperlinkedRelatedField(many=True,read_only=True,view_name='track-detail')class Meta:model = Albumfields = ['album_name', 'artist', 'tracks']
  • 默认HyperlinkedRelatedField字段是可读写的。可以使用read_only标志来更改此行为。

效果就是 tracks 属性将使用 Track 模型的主键即 id (我们没在模型中指定主键)来产生关联关系,并使用主键值。

将产生以下形式的序列化结果:

{'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

字段作用:
主模型序列化器中的SlugRelatedField字段可以使用从模型中的Slug字段来表示关联关系。可以使用目标上的字段来表示关系的目标。

  • django向模型提供Slug字段来创建更加完善的 URL。Rest Framework的SlugRelatedField字段也采用相同的理念。
  • django相关字段解释(slug)、在 Django 中生成 slug、django中slug是什么?有什么用?可以应用于什么地方?

字段参数:

  • slug_field:从模型中用来表示它的字段。这应该是唯一标识任何给定实例的字段。是必要参数。当使用
  • queryset:验证字段输入时用于模型实例查找的查询集。关系字段必须显式设置 queryset 或者 read_only=True
  • many:如果应用于多对一的关系,应该设置为 True。
  • allow_null:是否允许该字段接受 None 或为空关系接受空字符串。默认值为 False。

使用示例:

class AlbumSerializer(serializers.ModelSerializer):tracks = serializers.SlugRelatedField(many=True,read_only=True,slug_field='title')class Meta:model = Albumfields = ['album_name', 'artist', 'tracks']
  • 默认情况下,这个字段是可读写的。可以使用read_only标志来更改此行为。还必须确保模型中该字段设置了unique=True

效果就是 tracks 属性将使用 Track 模型的 title 字段来产生关联关系,并使用其值。

将产生以下形式的序列化结果:

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

(五)HyperlinkedIdentityField

字段作用:
主模型序列化器中的HyperlinkedIdentityField字段可以作为身份关系应用,例如HyperlinkedModelSerializer上的“url”字段。它也可以用于对象的属性。

字段参数:

  • view_name:应该用作关系目标的视图名称。如果使用标准的路由器类,则因该是一个格式为 modelname-detail 的字符串。是必要参数
  • lookup_field:应该用于查找的字段。应该对应于被引用视图上的 URL 关键字参数。默认设置是 pk。
  • lookup_url_kwarg:在 URL 配置文件中定义的关键字参数的名称,该参数是应该用于查找字段。默认使用与lookup_field相同的值。
  • format:如果使用格式后缀,超链接字段将为目标使用相同的格式后缀,除非使用format参数重写。

使用示例:

class AlbumSerializer(serializers.HyperlinkedModelSerializer):track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')class Meta:model = Albumfields = ['album_name', 'artist', 'track_listing']
  • 这个字段是只读写的。

效果就是 tracks 属性将使用 Track 模型的主键即 id (我们没在模型中指定主键)来产生关联关系,并使用主键值。

将产生以下形式的序列化结果:

{'album_name': 'The Eraser','artist': 'Thom Yorke','track_listing': 'http://www.example.com/api/track_list/12/',
}

四,嵌套关系

与在序列化器中使用序列化关系字段专门序列化模型间关系的方式所不同的是,序列化器本身还能作为序列化字段来表示一种模型间的嵌套关系。例如:

class TrackSerializer(serializers.ModelSerializer):class Meta:model = Trackfields = ['order', 'title', 'duration']class AlbumSerializer(serializers.ModelSerializer):tracks = TrackSerializer(many=True, read_only=True)class Meta:model = Albumfields = ['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 = Trackfields = ('order', 'title', 'duration')class AlbumSerializer(serializers.ModelSerializer):tracks = TrackSerializer(many=True)class Meta:model = Albumfields = ('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>

五,自定义关系字段

如果希望实现在现有的关系样式都不适合的输出需求时,则可以自定义关系字段:子类化RelatedField,并实现.to_representation(self, value)方法:

  • 此方法需要value参数(通常是一个模型实例),并应该返回所需要的序列化表示形式。
import timeclass 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 = Albumfields = ['album_name', 'artist', 'tracks']

效果如下:

{'album_name': 'Sometimes I Wish We Were an Eagle','artist': 'Bill Callahan','tracks': ['Track 1: Jim Cain (04:39)','Track 2: Eid Ma Clack Shaw (04:19)','Track 3: The Wind and the Dove (04:34)',...]
}

如果希望实现可读写的关系字段,则必须实现.to_internal_value(self, data)方法。

如果希望提供基于上下文的动态queryset,则需要重写.get_queryset(self),而不是在类上或初始化字段时指定.queryset

六,自定义超链接字段

如果希望自定义超链接字段的行为,以表示需要多个查询字段的 URL,则可以通过子类化 HyperlinkedRelatedField 来实现。有两个方法重需要写:

1, get_url(self, obj, view_name, request, format):用于将对象实例映射到其 URL 表示。

  • 如果 view_namelookup_field 属性未配置为正确匹配 URL,可能会引发 NoReverseMatch

2,get_object(self, queryset, view_name, view_args, view_kwargs):用于支持可写的超链接字段,以便将传入的 URL 映射回它们表示的对象。对于只读的超链接字段,无需重写此方法。

  • 此方法的返回值应该是与匹配的 URL 参数对应的对象,可能会引发 ObjectDoesNotExist 异常

假设我们有一个 customer 对象的 URL,它接受两个关键字参数:

/api/<organization_slug>/customers/<customer_pk>/

这时不能用仅接受单个查找字段的默认实现来表示,就需要重写 HyperlinkedRelatedField 以获得我们想要的行为:

from rest_framework import serializers
from rest_framework.reverse import reverseclass CustomerHyperlink(serializers.HyperlinkedRelatedField):# 我们将它们定义为类属性,因此我们不需要将它们作为参数传递。view_name = 'customer-detail'queryset = Customer.objects.all()def get_url(self, obj, view_name, request, format):url_kwargs = {'organization_slug': obj.organization.slug,'customer_pk': obj.pk}return reverse(view_name, kwargs=url_kwargs, request=request, format=format)def get_object(self, view_name, view_args, view_kwargs):lookup_kwargs = {'organization__slug': view_kwargs['organization_slug'],'pk': view_kwargs['customer_pk']}return self.get_queryset().get(**lookup_kwargs)

请注意,如果想将此样式与通用视图一起使用,那么还需要在视图上重写 .get_object 以获得正确的查找行为。

官方建议还是尽可能使用序列化关系字段 API ​​,但适度使用嵌套的 URL 样式也是合理的。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/BpKjFTlL.shtml

相关文章

Django官方文档

一、文档地址 https://docs.djangoproject.com/zh-hans/3.2/ 1.1 编写你的第一个 Django 应用&#xff0c;第 1 部分 1.1.1 创建项目 使用django的系统工具django-admin执行指令&#xff0c;即可创建 django-admin startproject mysite 目录结构显示如下 mysite/manage.…

WPF:WPF原生布局说明

前言 WPF在国内讨论度很小&#xff0c;我在这里记录一下WPF简单的原生控件是如何使用的&#xff0c;顺便回忆一下WPF的基础知识&#xff0c;有些忘记的比较厉害了 WPF简介 WPF是微软推出的桌面UI软件&#xff0c;是我觉得最早实现MVVM&#xff08;数据驱动事务&#xff09;&…

WPF界面美化(整体作用到控件),一步步教你使用FirstFloor.ModernUI

开发工具&#xff1a;VS2015 1、获取相关DLL(通过NuGet或者GitHub上下载的源码中获得)&#xff0c;并在项目中添加引用 FirstFloor.ModernUI.dll Microsoft.Windows.Shell.dll UIShell.OSGi(这个是我运行程序时报的错误"未能加载文件或程序集"&#xff0c;然后在…

WPF 极简风格登录界面

UI使用MaterialDesign&#xff0c;先看界面 一、界面 极简登录界面 二、下载MaterialDesign包 我使用的是VS2019&#xff0c;选择要引入MaterialDesign包的项目&#xff0c;鼠标右击选择NuGet程勋包 在浏览页签中输入MaterialDesign&#xff0c;下载MaterialDesignColors和Ma…

WPF绘制自定义窗口

简介&#xff1a; 原文:WPF绘制自定义窗口 WPF是制作界面的一大利器&#xff0c;下面就用WPF模拟一下360的软件管理界面&#xff0c;360软件管理界面如下&#xff1a; 界面不难&#xff0c;主要有如下几个要素&#xff1a; 窗体的圆角 自定义标题栏及按钮 自定义状态栏 窗体的半…

WPF简单UI菜单设计

UI效果如下&#xff1a; XAML 设计&#xff1a; <Window x:Class"简单菜单设计.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://…

WPF真入门教程05--UI布局2

这一节&#xff0c;来学习下ComboBox下拉框&#xff0c;Border边框控件&#xff0c;Image图片控件&#xff0c;CheckBox复选框&#xff0c; 这些发挥着不同的作用&#xff0c;是布局基础组成部分&#xff0c;从左侧拖控件到右边&#xff0c;完成以下代码&#xff1a; <Wind…

WPF基本介绍

WPF基本介绍 WPF&#xff08;Windows Presentation Foundation&#xff09;是&#xff08;微软推出的&#xff09;基于Windows的用户界面框架&#xff0c;属于.NET Framework 3.0的一部分。WPF提供了统一的编程模型&#xff0c;语言和框架&#xff0c;做到了分离界面设计人员与…

WPF UI介面的革新

透過 Microsoft 對 Windows Vista 及 WPF 的強力行 銷&#xff0c;相信許多讀者對於WPF的UI能力只有驚豔二字可以形容&#xff0c;對於如何使用WPF來達到這些效果&#xff0c;基於雜誌與網路上已有相當多的文章討論&#xff0c;筆者於此就不再重述了&#xff0c;直接將主軸放在…

WPF界面设计—撸大师

WPF界面设计,模仿了金山卫士,360,鲁大师的界面! <!--无边框窗体--><Style x:Key="NoResize_window" TargetType="{x:Type Window}"> <Setter Property="AllowsTransparency" Value="true"/> <Setter Prope…

WPF - 简单的UI框架

实现了一个简单的WPF应用程序UI框架 &#xff0c;分享出来。界面效果图如下&#xff1a; 运行效果如下&#xff1a; 打算持续更新&#xff0c;将左侧面板所有功能模块全给实现了。 喜欢的可以下载源码体验&#xff1a;https://github.com/DuelWithSelf/WPFEffects 左侧分类导览…

WPF真入门教程04--UI布局1

大家都知道&#xff1a;UI是做好一个软件很重要的因素&#xff0c;如果没有一个漂亮的UI&#xff0c;功能做的再好也无法吸引很多用户使用&#xff0c;而且没有漂亮的界面&#xff0c;那么普通用户会感觉这个软件没有多少使用价值。 WPF系统基于流布局的标准&#xff0c;开发人…

WPF UI界面控件篇

WPF UI界面控件篇 布局控件&#xff1a;是任何用户界面的基础&#xff0c;排列应用中的 UI 元素。 文本、按钮和图像等元素都需要规定自己位置和行为方式&#xff0c;构建基块称为“控件”&#xff0c;有时亦称为“元素”。 <Window x:Class"UsingLayoutsApp.Wpf.Mai…

WPF(一) WPF基本控件与布局

​ WPF&#xff08;Windows Presentation Foundation&#xff09;是微软推出的基于Windows的用户界面框架&#xff0c;中文译为“Windows呈现基础”&#xff0c;属于.NET Framework 3.0的一部分。WPF类似于WinForm技术框架&#xff0c;但是相比于WinForm&#xff0c;WPF对大部分…

WPF炫酷界面设计

一.效果展示&#xff08;多层次&#xff09; 二.制作流程 1.在vs2012中建立一个wpf程序 2.建立一个主页面&#xff08;.cs&#xff09;(注&#xff1a;C#程序每一个页面都由两个文件构成一个axml一个cs&#xff0c;一个前端文件一个后台文件) 3.在主页面中添加按钮&#xff0c;…

WPF界面设计工具---Blend学习(一)

文章目录 前言一.初用Blend之喜二.使用Blend1.Blend工具版本 前言 最近在空闲时间学习WPF界面设计工具Blend&#xff0c;之前写WPF的界面都是完全依靠手敲代码的方式&#xff0c;这种方式往往很低效率而且很难做到一些复杂的效果。比如动画&#xff0c;手敲代码实现动画的话&a…

C# WPF 一个设计界面

微信公众号&#xff1a;Dotnet9&#xff0c;网站&#xff1a;Dotnet9&#xff0c;问题或建议&#xff1a;请网站留言&#xff0c; 如果对您有所帮助&#xff1a;欢迎赞赏。 C# WPF 一个设计界面 今天正月初三&#xff0c;大家在家呆着挺好&#xff0c;不要忘了自我充电。 武汉…

WPF界面设计

目录 1.设计一个优美的注册界面1.实现效果2.代码展示 2.简易登录按钮设计1.实现效果2.代码展示 3.设计一个优美的注册登录界面&#xff08;连接数据库&#xff09;1.实现效果2.代码展示 4.设计一个简单的在线教育系统界面1.实现效果2.代码展示 5. 设计一个Dashboard1.实现效果2…

WPF实例系列一:登录、注册界面设计

WPF实例系列一&#xff1a;登录、注册界面设计 文章目录 WPF实例系列一&#xff1a;登录、注册界面设计前言一、实例演示1. 登录界面展示2. 注册界面展示3. 数据存储4. 效果演示 二、结构及源码1.主界面跳转登录界面设计2.登录界面设计3.注册界面设计4.Excel保存数据类设计5.源…

C# WPF界面设计参考 工控机上位机界面 美观炫酷的现代化风格界面设计实际案例分享 界面设计代码

1.动图效果展示 2.界面1 3.界面2 4.界面3 需要界面效果代码的可留言联系博主