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

相关文章

解析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

Django之定时任务django-crontab的实现

《Django之定时任务django-crontab的实现》Django可以使用第三方库如django-crontab来实现定时任务的调度,本文主要介绍了Django之定时任务django-cront... 目录crontab安装django-crontab注册应用定时时间格式定时时间示例设置定时任务@符号

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

Django序列化中SerializerMethodField的使用详解

《Django序列化中SerializerMethodField的使用详解》:本文主要介绍Django序列化中SerializerMethodField的使用,具有很好的参考价值,希望对大家有所帮... 目录SerializerMethodField的基本概念使用SerializerMethodField的