django rest framework关联关系——Serializer relations

2023-11-20 21:32

本文主要是介绍django rest framework关联关系——Serializer relations,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://django-rest-framework.org/api-guide/relations.html

Serializer relations

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

— Linus Torvalds

Relational fields are used to represent model relationships. They can be applied to ForeignKeyManyToManyField andOneToOneField relationships, as well as to reverse relationships, and custom relationships such as GenericForeignKey.


Note: The relational fields are declared in relations.py, but by convention you should import them from the serializersmodule, using from rest_framework import serializers and refer to fields as serializers.<FieldName>.


API Reference

In order to explain the various types of relational fields, we'll use a couple of simple models for our examples. Our models will be for music albums, and the tracks listed on each album.

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')order = models.IntegerField()title = models.CharField(max_length=100)duration = models.IntegerField()class Meta:unique_together = ('album', 'order')order_by = 'order'def __unicode__(self):return '%d: %s' % (self.order, self.title)

RelatedField

RelatedField may be used to represent the target of the relationship using it's __unicode__ method.

For example, the following serializer.

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

Would serialize to the following representation.

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

This field is read only.

Arguments:

  • many - If applied to a to-many relationship, you should set this argument to True.

PrimaryKeyRelatedField

PrimaryKeyRelatedField may be used to represent the target of the relationship using it's primary key.

For example, the following serializer:

class AlbumSerializer(serializers.ModelSerializer):tracks = PrimaryKeyRelatedField(many=True, read_only=True)class Meta:model = Albumfields = ('album_name', 'artist', 'tracks')

Would serialize to a representation like this:

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

By default this field is read-write, although you can change this behavior using the read_only flag.

Arguments:

  • many - If applied to a to-many relationship, you should set this argument to True.
  • required - If set to False, the field will accept values of None or the empty-string for nullable relationships.
  • queryset - By default ModelSerializer classes will use the default queryset for the relationship. Serializer classes must either set a queryset explicitly, or set read_only=True.

HyperlinkedRelatedField

HyperlinkedRelatedField may be used to represent the target of the relationship using a hyperlink.

For example, the following serializer:

class AlbumSerializer(serializers.ModelSerializer):tracks = HyperlinkedRelatedField(many=True, read_only=True,view_name='track-detail')class Meta:model = Albumfields = ('album_name', 'artist', 'tracks')

Would serialize to a representation like this:

{'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',...]
}

By default this field is read-write, although you can change this behavior using the read_only flag.

Arguments:

  • view_name - The view name that should be used as the target of the relationship. required.
  • many - If applied to a to-many relationship, you should set this argument to True.
  • required - If set to False, the field will accept values of None or the empty-string for nullable relationships.
  • queryset - By default ModelSerializer classes will use the default queryset for the relationship. Serializer classes must either set a queryset explicitly, or set read_only=True.
  • slug_field - The field on the target that should be used for the lookup. Default is 'slug'.
  • pk_url_kwarg - The named url parameter for the pk field lookup. Default is pk.
  • slug_url_kwarg - The named url parameter for the slug field lookup. Default is to use the same value as given forslug_field.
  • format - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the format argument.

SlugRelatedField

SlugRelatedField may be used to represent the target of the relationship using a field on the target.

For example, the following serializer:

class AlbumSerializer(serializers.ModelSerializer):tracks = SlugRelatedField(many=True, read_only=True, slug_field='title')class Meta:model = Albumfields = ('album_name', 'artist', 'tracks')

Would serialize to a representation like this:

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

By default this field is read-write, although you can change this behavior using the read_only flag.

When using SlugRelatedField as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with unique=True.

Arguments:

  • slug_field - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, usernamerequired
  • many - If applied to a to-many relationship, you should set this argument to True.
  • required - If set to False, the field will accept values of None or the empty-string for nullable relationships.
  • queryset - By default ModelSerializer classes will use the default queryset for the relationship. Serializer classes must either set a queryset explicitly, or set read_only=True.

HyperlinkedIdentityField

This field can be applied as an identity relationship, such as the 'url' field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:

class AlbumSerializer(serializers.HyperlinkedModelSerializer):track_listing = HyperlinkedIdentityField(view_name='track-list')class Meta:model = Albumfields = ('album_name', 'artist', 'track_listing')

Would serialize to a representation like this:

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

This field is always read-only.

Arguments:

  • view_name - The view name that should be used as the target of the relationship. required.
  • slug_field - The field on the target that should be used for the lookup. Default is 'slug'.
  • pk_url_kwarg - The named url parameter for the pk field lookup. Default is pk.
  • slug_url_kwarg - The named url parameter for the slug field lookup. Default is to use the same value as given forslug_field.
  • format - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the format argument.

Nested relationships

Nested relationships can be expressed by using serializers as fields.

If the field is used to represent a to-many relationship, you should add the many=True flag to the serializer field.

Note that nested relationships are currently read-only. For read-write relationships, you should use a flat relational style.

Example

For example, the following serializer:

class TrackSerializer(serializers.ModelSerializer):class Meta:model = Trackfields = ('order', 'title')class AlbumSerializer(serializers.ModelSerializer):tracks = TrackSerializer(many=True)class Meta:model = Albumfields = ('album_name', 'artist', 'tracks')

Would serialize to a nested representation like this:

{'album_name': 'The Grey Album','artist': 'Danger Mouse''tracks': [{'order': 1, 'title': 'Public Service Annoucement'},{'order': 2, 'title': 'What More Can I Say'},{'order': 3, 'title': 'Encore'},...],
}

Custom relational fields

To implement a custom relational field, you should override RelatedField, and implement the .to_native(self, value)method. This method takes the target of the field as the value argument, and should return the representation that should be used to serialize the target.

If you want to implement a read-write relational field, you must also implement the .from_native(self, data) method, and addread_only = False to the class definition.

Example

For, example, we could define a relational field, to serialize a track to a custom string representation, using it's ordering, title, and duration.

import timeclass TrackListingField(serializers.RelatedField):def to_native(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')

This custom field would then serialize to the following representation.

{'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)',...]
}

Further notes

Reverse relations

Note that reverse relationships are not automatically generated by the ModelSerializer and HyperlinkedModelSerializerclasses. To include a reverse relationship, you cannot simply add it to the fields list.

The following will not work:

class AlbumSerializer(serializers.ModelSerializer):class Meta:fields = ('tracks', ...)

Instead, you must explicitly add it to the serializer. For example:

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

By default, the field will uses the same accessor as it's field name to retrieve the relationship, so in this example, Albuminstances would need to have the tracks attribute for this relationship to work.

The best way to ensure this is typically to make sure that the relationship on the model definition has it's related_nameargument properly set. For example:

class Track(models.Model):album = models.ForeignKey(Album, related_name='tracks')...

Alternatively, you can use the source argument on the serializer field, to use a different accessor attribute than the field name. For example.

class AlbumSerializer(serializers.ModelSerializer):tracks = serializers.PrimaryKeyRelatedField(many=True, source='track_set')

See the Django documentation on reverse relationships for more details.

Generic relationships

If you want to serialize a generic foreign key, you need to define a custom field, to determine explicitly how you want serialize the targets of the relationship.

For example, given the following model for a tag, which has a generic relationship with other arbitrary models:

class TaggedItem(models.Model):"""Tags arbitrary model instances using a generic relation.See: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/"""tag_name = models.SlugField()content_type = models.ForeignKey(ContentType)object_id = models.PositiveIntegerField()tagged_object = GenericForeignKey('content_type', 'object_id')def __unicode__(self):return self.tag

And the following two models, which may be have associated tags:

class Bookmark(models.Model):"""A bookmark consists of a URL, and 0 or more descriptive tags."""url = models.URLField()tags = GenericRelation(TaggedItem)class Note(models.Model):"""A note consists of some text, and 0 or more descriptive tags."""text = models.CharField(max_length=1000)tags = GenericRelation(TaggedItem)

We could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized.

class TaggedObjectRelatedField(serializers.RelatedField):"""A custom field to use for the `tagged_object` generic relationship."""def to_native(self, value):"""Serialize tagged objects to a simple textual representation."""                            if isinstance(value, Bookmark):return 'Bookmark: ' + value.urlelif isinstance(value, Note):return 'Note: ' + value.textraise Exception('Unexpected type of tagged object')

If you need the target of the relationship to have a nested representation, you can use the required serializers inside the.to_native() method:

    def to_native(self, value):"""Serialize bookmark instances using a bookmark serializer,and note instances using a note serializer."""                            if isinstance(value, Bookmark):serializer = BookmarkSerializer(value)elif isinstance(value, Note):serializer = NoteSerializer(value)else:raise Exception('Unexpected type of tagged object')return serializer.data

Note that reverse generic keys, expressed using the GenericRelation field, can be serialized using the regular relational field types, since the type of the target in the relationship is always known.

For more information see the Django documentation on generic relations.


Deprecated APIs

The following classes have been deprecated, in favor of the many=<bool> syntax. They continue to function, but their usage will raise a PendingDeprecationWarning, which is silent by default.

  • ManyRelatedField
  • ManyPrimaryKeyRelatedField
  • ManyHyperlinkedRelatedField
  • ManySlugRelatedField

The null=<bool> flag has been deprecated in favor of the required=<bool> flag. It will continue to function, but will raise aPendingDeprecationWarning.

In the 2.3 release, these warnings will be escalated to a DeprecationWarning, which is loud by default. In the 2.4 release, these parts of the API will be removed entirely.

For more details see the 2.2 release announcement.


这篇关于django rest framework关联关系——Serializer relations的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/397577

相关文章

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

POJ1269 判断2条直线的位置关系

题目大意:给两个点能够确定一条直线,题目给出两条直线(由4个点确定),要求判断出这两条直线的关系:平行,同线,相交。如果相交还要求出交点坐标。 解题思路: 先判断两条直线p1p2, q1q2是否共线, 如果不是,再判断 直线 是否平行, 如果还不是, 则两直线相交。  判断共线:  p1p2q1 共线 且 p1p2q2 共线 ,共线用叉乘为 0  来判断,  判断 平行:  p1p

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简

Yii框架relations的使用

通过在 relations() 中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问资讯的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。 前提条件 在组织数据库时,需要使用主键与外键约束才能使用ActiveReocrd的关系操作; 场景 申明关系 两张表之间的关系无非三种:一对多;一对一;多对多; 在

读软件设计的要素04概念的关系

1. 概念的关系 1.1. 概念是独立的,彼此间无须相互依赖 1.1.1. 一个概念是应该独立地被理解、设计和实现的 1.1.2. 独立性是概念的简单性和可重用性的关键 1.2. 软件存在依赖性 1.2.1. 不是说一个概念需要依赖另一个概念才能正确运行 1.2.2. 只有当一个概念存在时,包含另一个概念才有意义 1.3. 概念依赖关系图简要概括了软件的概念和概念存在的理

数据依赖基础入门:函数依赖与数据库设计的关系

在数据库设计中,数据依赖 是一个重要的概念,它直接影响到数据库的结构和性能。函数依赖 作为数据依赖的一种,是规范化理论的基础,对数据库设计起着至关重要的作用。如果你是一名数据库设计的初学者,这篇文章将帮助你理解函数依赖及其在数据库设计中的应用。 什么是数据依赖? 数据依赖 是指同一关系中属性间的相互依赖和制约关系,它是数据库设计中语义的体现。在现实世界中,数据之间往往存在某种依赖关系,而这

C++ STL关联容器Set与集合论入门

1. 简介 Set(集合)属于关联式容器,也是STL中最实用的容器,关联式容器依据特定的排序准则,自动为其元素排序。Set集合的底层使用一颗红黑树,其属于一种非线性的数据结构,每一次插入数据都会自动进行排序,注意,不是需要排序时再排序,而是每一次插入数据的时候其都会自动进行排序。因此,Set中的元素总是顺序的。 Set的性质有:数据自动进行排序且数据唯一,是一种集合元素,允许进行数学上的集合相

c++ 和C语言的兼容性关系

C++ 和 C 语言有很高的兼容性,但也存在一些差异和限制。下面是它们的兼容性关系的详细介绍: 兼容性 C++ 是 C 的超集: C++ 语言设计为兼容 C 语言的语法和功能,大部分 C 代码可以在 C++ 编译器中编译运行。 标准库兼容性: C++ 标准库包含了 C 标准库的内容,如 stdio.h、stdlib.h、string.h 等头文件,但 C++ 的标准库也提供了额外的功能,如