本节大纲

  1、Serializer fields

  2、Serializer relations

Serializer fields

1、serializer 字段定义在fields.py文件内
2、导入from rest_framework import serializers
3、引用serializers.<FieldName>

核心参数

read_only 

# 默认是False,True的时候在序列化显示的时候展示,在反序列化实例进行创建或者更新的时候不被使用。

write_only

# 默认是false,True的时候可以用来更新或者创建实例,在序列化呈现的时候不显示

required

# 默认是True,False的时候可以遗漏此字段,如果不存在,就不会显示

default

# 提供一个默认值

allow_null

# 默认是false

source

# 默认指向字段名;EmailField(source='user.email');URLField(source='get_absolute_url')
# source='*' 有一个特殊的含义,要用来显示整个对象,在嵌套展示的时候很有用

validator

# 验证器,通过返回数据,不通过引发报错,Django内置的serializers.ValidationError

error_messages

# 错误信息的字典

label

# 标签,可以用来当HTML标签的表单字段

help_text

# 帮助提示

initial

# 预填充字段值
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
day = serializers.DateField(initial=datetime.date.today)

style

# 用来控制字段的渲染
# Use <input type="password"> for the input.
password = serializers.CharField(
style={'input_type': 'password'}
) # Use a radio input instead of a select input.
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'}
)

主要还是因为相关的字段太多,楼主觉得没必要一次性看好,有需求的时候查找可能会更好一点。

http://www.django-rest-framework.org/api-guide/fields/

Serializer relations

关系字段,顾名思义,用来表示模型之间的关系,可以用ForeignKey, ManyToManyField和OneToOneField来表示关系,客制化关系可以用GenericForeignKey

关系字段是在relations.py文件内申明的,但是你应该从serializers模块导入,使用from rest_framework import serializers然后serializers.<FieldName>

Inspecting relationships

打开pycharm的python console或者在terminal启动python3 manage.py shell输入

from app01.serializers import PersonModelSerializer
serializer = PersonModelSerializer()
print(repr(serializer))
PersonModelSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(max_length=128)
age = IntegerField()
get_gender = ReadOnlyField()
get_job = ReadOnlyField()
modify_time = DateTimeField(read_only=True)

API Reference

为了解释不同类型的关系字段,我们将使用简单的模型作为示例。

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 __unicode__(self):
return '%d: %s' % (self.order, self.title)

StringRelatedField

StringRelatedField可以被用来展示目的关系使用它的__str__方法(这里官网上给的是__unicode__方法,但楼主测试下来并不是)

class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True) class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')

将会被序列化成下面的样子

{'album_name': 'reputation', 'artist': 'Taylor Swift', 'tracks': ['reputation: Look What you make me do', 'reputation: Delicate']}

字段只读,如果对应多个关系,需要添加many=True

PrimaryKetRelatedField

PrimaryKeyRelatedField可以使用主键来表示目的关系

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

结果如下

{'album_name': 'reputation', 'artist': 'Taylor Swift', 'tracks': [2, 3]}

默认这个字段可读写,你可以改变这个行为通过使用read_only标志

参数

queryset, many,allow_null,pk_field...(pk_field=UUIDField(format='hex'))

HyperlinkedRelatedField

HyperlinkedRelatedField可以通过超链接来显示目的关系

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

结果

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

这边就不细讲这个具体实现了,可以查看serializer章节,通过链接https://www.cnblogs.com/wuzdandz/p/9631032.html 并查找HyperlinkedModelSerializer关键字搜索标题

参数

view_name
queryset
many
allow_null
lookup_field
look_url_kwarg
format

SlugRelatedField

SlugRelatedField可以用来用目的对象的一个字段来表示关系。

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

序列化呈现

{'album_name': 'reputation', 'artist': 'Taylor Swift', 'tracks': ['Look What you make me do', 'Delicate']}

同样SlugRelatedField是一个可读写的字段,你可以通过read_only来修改行为。当使用SlugRelatedField作为一个可读写的字段,你通常想确保SlugRelatedField对应model里面unique=True的一个字段。

参数

slug_field,queryset,many,allow_null

HyperlinkedIdentityField

这个应该也不需要说了,有问题看下面的还是上面的链接https://www.cnblogs.com/wuzdandz/p/9631032.html

Nested relationships

嵌套关系可以通过使用serializers作为字段来描述。

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_name': 'reputation',
'artist': 'Taylor Swift',
'tracks': [
OrderedDict([('order', 2), ('title', 'Look What you make me do'), ('duration', 2)]),
OrderedDict([('order', 3), ('title', 'Delicate'), ('duration', 4)])
]
}

Writable nested serializers

默认嵌套的serializers是只读的,如果你想要对嵌套的serializer字段支持写操作,就需要创建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>

自定义create里面我们pop出来了tracks的数据然后单独对它进行了创建。

Custom relationnal fields

在少数案例里面没有现存的关系格式满足你想要的表现形式,你可以构造一个完整的客制化的关系字段用来描述从模型实例生产的准确的输出形式。要构建一个客制化的关系字段,你应该重写RelatedField和构建.to_representation(self, value). 这个方法会把目的字段的值作为value参数,并返回此对象序列化的表现。这个value参数通常将会是一个模型(model)实例.

想要基于context提供一个动态的queryset,你也可以重写.get_queryset(self)代替在类上标注.queryset或者当初始化字段时

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

结果:

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

Custom hyperlinked fields

在一些案例里面,你可能需要客制化一个hyperlinked字典的行为,为了呈现URLs,可能需要不止一个查找字段。

你可以通过重写HyperlinkedRelatedField获取。有两个你可以重写的方法

get_url(self, obj, view_name, request, format)  # 被用来映射对象实例到url呈现;可以引发NoReverseMatch如果view_name和lookup_field属性没有被正确的配置匹配url设置。
get_object()self, queryset, view_name, view_args, view_kwargs) # 实现可写的hyperlinked field,为了映射将传入的URLs到他们所代表的对象。只读的没必要重写。这个方法的返回值应该是对应匹配的url设置参数的对应的对象。可以引发ObjectDoesNotExist错误

我们有一个客制化对象的url,里面有2个关键字参数

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

这种用默认的执行不能被展示,因为只接受一个单独的查找字段。这个示例里面,我们需要重写HyperlinkedRelatedField来获得我们需要的行为:

from rest_framework import serializers
from rest_framework.reverse import reverse class CustomerHyperlink(serializers.HyperlinkedRelatedField):
# We define these as class attributes, so we don't need to pass them as arguments.
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)

源码如下

     def get_object(self, view_name, view_args, view_kwargs):
"""
Return the object corresponding to a matched URL. Takes the matched URL conf arguments, and should return an
object instance, or raise an `ObjectDoesNotExist` exception.
"""
lookup_value = view_kwargs[self.lookup_url_kwarg]
lookup_kwargs = {self.lookup_field: lookup_value}
return self.get_queryset().get(**lookup_kwargs) def get_url(self, obj, view_name, request, format):
"""
Given an object, return the URL that hyperlinks to the object. May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
attributes are not configured to correctly match the URL conf.
"""
# Unsaved objects will not yet have a valid URL.
if hasattr(obj, 'pk') and obj.pk in (None, ''):
return None lookup_value = getattr(obj, self.lookup_field)
kwargs = {self.lookup_url_kwarg: lookup_value}
return self.reverse(view_name, kwargs=kwargs, request=request, format=format)

上面的列相当于继承HyperlinkedRelatedField,并重写了里面的方法。

Customizing the HTML display

模型的内置__str__方法将用于生成用于填充choices属性的对象的字符串表示。这些choices被用来填充可浏览API的选择HTML输入。

为了对于这些输入提供客制化的表现,可以重写RelatedFIeld子类的display_value()方法。这个方法将会接收一个模型对象,并应该返回一个合适的字符串来展示。

class TrackPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def display_value(self, instance):
return 'Track: %s' % (instance.title)

Select field cutoffs

可浏览的API默认只展示最多1000条选中的对象。2个关键字参数可以用来控制这个行为

html_cutoff
设置这个,HTML选择下拉将显示的最大选择数。设置为None所有限制失效。默认1000 html_vutoff_text
如果在HTML选择下拉中截断了最大数量的项目,则将显示文本指示符。默认'More than {count} items...'

你也可以控制这些通过设定全局参数HTML_SELECT_CUTOFF和HTML_SELECT_CUTOFF_TEXT

在强制执行中断的情况下,您可能希望使用HTML表单中的普通输入字段。您可以使用style关键字参数。例如:

assigned_to = serializers.SlugRelatedField(
queryset=User.objects.all(),
slug_field='username',
style={'base_template': 'input.html'}
)

Reverse relations

注意,反转管理没有自动的被包括在ModelSerializer和HyperlinkedModelSerializer类里。为了能实现,你必须清楚的添加它到字段列表里。

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

你通常想确保已经设置了一个合适的related_name参数在关系上,你可以使用它作为字段名。

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

如果没有设置related_name在反转关系上,你需要使用自动生成的关联名称在fields参数内

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

Generic relationships

如果你先要序列化一个通用的外间,你需要定义一个自定义字段,清楚的决定你想要目的关系怎么序列化

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

下面2个模型类有关联:

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)

我们可以自定义一个字段用来序列化目的示例

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

如果需要目的关系有一个嵌套的表示,你可以使用需要的serializer在.to_representation()方法内

 def to_representation(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

Django REST Framework API Guide 05的更多相关文章

  1. Django REST Framework API Guide 01

    之前按照REST Framework官方文档提供的简介写了一系列的简单的介绍博客,说白了就是翻译了一下简介,而且翻译的很烂.到真正的生产时,就会发现很鸡肋,连熟悉大概知道rest framework都 ...

  2. Django REST Framework API Guide 03

    本节大纲 1.Routers 2.Parsers 3.Renderers Routers Usage from rest_framework import routers router = route ...

  3. Django REST Framework API Guide 08

    1.Filtering 2.Pagination FIltering GenericAPIView的子类筛选queryset的简单方法是重写.get_quueryset()方法. 1.根据当前用户进行 ...

  4. Django REST Framework API Guide 06

    本节大纲 1.Validators 2.Authentication Validators 在REST框架中处理验证的大多数时间,您将仅仅依赖于缺省字段验证,或在序列化器或字段类上编写显式验证方法.但 ...

  5. Django REST Framework API Guide 04

    本节大纲 1.serializers 1.Serializers Serializers允许复杂的数据,像queryset和模型实例转换成源生的Python数据类型.从而可以更简单的被渲染成JSON, ...

  6. Django REST Framework API Guide 02

    本节大纲 1.Generic Views 2.ViewSets  1.Generic Views CBV的主要的一个优点就是极大的允许了对于代码的从用.自然,rest framework取其优势,提供 ...

  7. Django REST Framework API Guide 07

    本节大纲 1.Permissions 2.Throttling Permissions 权限是用来授权或者拒绝用户访问API的不同部分的不同的类的.基础的权限划分 1.IsAuthenticated ...

  8. Django Rest Framework API指南

    Django Rest Framework API指南 Django Rest Framework 所有API如下: Request 请求 Response 响应 View 视图 Generic vi ...

  9. tastypie Django REST framework API [Hello JSON]

    tastypie is a good thing. Haven't test it thoroughly. Gonna need some provement. Now I will introduc ...

随机推荐

  1. Could not install the app on the device, read the error above for details. Make sure you have an Android emulator running or a device connected and have set up your Android development environment:

    Administrator@DESKTOP-EHCTIOR MINGW64 /d/react-native-eyepetizer (master) $ react-native run-android ...

  2. Remote debugger is in a background tab which may cause apps to perform slowly. Fix this by foregrounding the tab (or opening it in a separate window).

    先上代码: /** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow * ...

  3. GWAS研究可利用的数据库(持续更新)

    1.列表包括数据库名称.表型.是否能下载到基因型(genotype).是否能下载到GWAS结果文件(P值.效应值.SNP位点).目前收集到的有如下: 参考到这些数据库的文献:Genome-wide a ...

  4. 苹果电脑python3安装pillow模块

    我刚开始在苹果电脑自带的python 中安装了pillow模块,导致在后期我想在python3中安装pilow模块的时候 pip3 install pillow 但是总会提示错误说电脑中已经存在pil ...

  5. 踩过的坑—iphone手机H5样式兼容总结

    对一个前端开发者来说,最煎熬的莫过于"兼容"两个字了(说到这个词朋友们是不是身体一抖),哪怕对于工作多年的老油条来讲,也不是完全了解各种场景下的兼容性处理方法.在这里我就把我在工作 ...

  6. 跨域技术(JSONP与CROS)

    JSONP 我们发现,Web页面上调用js文件时不受是否跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>.<img>.&l ...

  7. 10 个 Linux 中方便的 Bash 别名

    10 个方便的 Bash 别名 1. 你有几次遇到需要解压 .tar 文件但无法记住所需的确切参数?别名可以帮助你!只需将以下内容添加到 .bash_profile 中,然后使用 untar File ...

  8. @JsonIgnore注解可以实现不返回前端字段

    import com.fasterxml.jackson.annotation.JsonIgnore; /** * 密码 */ @JsonIgnore private String password;

  9. angular,vue,react的基本语法—样式处理

    基本语法 样式处理: vue: 动态属性: v-bind:class 简写 :class react: 变量:class={selecter} angular: 指令:[ngClass]=" ...

  10. ruby数组操作方法汇总

    1.数组定义 arr1 = [] arr2 = Array.new arr3 = ['1','2','3'] 2.输出 print arr3,"\n" #123 puts arr3 ...