本节大纲

  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. ImageMagick 笔记: 索引颜色(index color)、锁定图层,透明 png 转 gif (保持清晰度)

    今天在处理一张 png 透明背景的图片,大小: 16KB, 尺寸: 400 x 300,用到一段代码,也许对以后有用. /** 带透明背景和阴影的png图片, 转换成 gif, [索引色] + [锁住 ...

  2. tensor flow中summary用法总结

    对于用法的总结详细的参见博文https://www.cnblogs.com/lyc-seu/p/8647792.html

  3. Luogu P4009 汽车加油行驶问题

    题目链接 \(Click\) \(Here\) 分层图..好长时间没写差点要忘了\(hhhhh\),其实思路还是很明了的. 注意需要强制消费. #include <bits/stdc++.h&g ...

  4. Go结构体

    当我们要表示同一种数据类型时候,可以用到数组,切片和字典. 当我们要表示不同的数据类型呢?这时候就要用到结构体了 一:定义struct 关键字 type 和 struct 来定义结构体 type st ...

  5. smarty实例

    login.php代码 <?phpinclude("../init.inc.php"); $smarty->display("login.html" ...

  6. MyBatis-SqlSessionFactory的创建

    Main 方法,mybatis 版本为 3.5.0 解析配置文件的所有信息,保存在 Configuration 中,返回包含 Configuration 的 DefaultSqlSession Map ...

  7. Sql Server 游标例子笔记

    create PROCEDURE total_mySaleDuty as BEGIN DECLARE @a int,@error int DECLARE @b int,@errorb int DECL ...

  8. Linux记录- Linux下限制rm -rf /

    操作说明: 为了防止在linux下执行操作的时候误操作rm -rf /,或者rm -rf 一些比较重要的目录,我们做以下操作来限制rm的删除 1.下载源码安装包 https://raw.githubu ...

  9. Sidetiq 定时任务

    class SidekiqCreateMonthPlanWorker #定时自动生成下月计划 include Sidekiq::Worker include Sidetiq::Schedulable ...

  10. SpringCloud微服务之跨服务调用后端接口

    SpringCloud微服务系列博客: SpringCloud微服务之快速搭建EurekaServer:https://blog.csdn.net/egg1996911/article/details ...