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

相关文章

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

Python库 Django 的简介、安装、用法入门教程

《Python库Django的简介、安装、用法入门教程》Django是Python最流行的Web框架之一,它帮助开发者快速、高效地构建功能强大的Web应用程序,接下来我们将从简介、安装到用法详解,... 目录一、Django 简介 二、Django 的安装教程 1. 创建虚拟环境2. 安装Django三、创

Java中数组与栈和堆之间的关系说明

《Java中数组与栈和堆之间的关系说明》文章讲解了Java数组的初始化方式、内存存储机制、引用传递特性及遍历、排序、拷贝技巧,强调引用数据类型方法调用时形参可能修改实参,但需注意引用指向单一对象的特性... 目录Java中数组与栈和堆的关系遍历数组接下来是一些编程小技巧总结Java中数组与栈和堆的关系关于

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

Django HTTPResponse响应体中返回openpyxl生成的文件过程

《DjangoHTTPResponse响应体中返回openpyxl生成的文件过程》Django返回文件流时需通过Content-Disposition头指定编码后的文件名,使用openpyxl的sa... 目录Django返回文件流时使用指定文件名Django HTTPResponse响应体中返回openp

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

解决Entity Framework中自增主键的问题

《解决EntityFramework中自增主键的问题》:本文主要介绍解决EntityFramework中自增主键的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Entity Framework中自增主键问题解决办法1解决办法2解决办法3总结Entity Fram

对Django中时区的解读

《对Django中时区的解读》:本文主要介绍对Django中时区的解读方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景前端数据库中存储接口返回AI的解释问题:这样设置的作用答案获取当前时间(自动带时区)转换为北京时间显示总结背景设置时区为北京时间 TIM