一年前就已经用过restframework, 当时觉得这个只是给web框架打辅助的, 他能实现的我也都实现(可能没有那么好用, 嘿嘿)

但是我有一种东西叫做效率, 时间就是金钱, 别人造好的就直接用就可以了, 自己其实没必要在去重复.

  最近写一个调查问卷系统, 利用了以下知识点

  1. django

  2. restframework(重点重点重点)

  3. Vue

  4. axios

  5. ..............

  从这个项目中我对restframework有了重新的认识, 互联网的精神就是共享, 所以就分享出来了

restframework的序列化器

当项目的架构为前后端分离时, 前后端的数据交互就变的尤为的重要, restframework的序列化过程无外乎一下6步:

  1. 获取数据集合(queryset)

  2. 获取序列化器

  3. 过滤, 排序

  4. 分页

  5. 对处理好的数据进行进行序列化

  5. 响应序列化结果

这些都是最基本的步骤, 但是在每一步中都蕴藏了大量的小技术, 利用这些小技术, 也许你正在头疼的一小问题就能找到答案, 哈哈, 细节决定成败

选择性的对字段进行序列化

官方是这样说的

For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so

王氏翻译: 例如,如果您希望能够在初始化序列化器时设置序列化器应该使用哪些字段,您可以创建这样的序列化器类:

这个类就长这样

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
""" def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None) # Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) if fields is not None:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)

之后你的序列化器就可以继承这个类了, 但是要注意这个类是在ModelSerializer之上的

下面就是使用方法

序列化器

class BookSerializers(DynamicFieldsModelSerializer):
class Meta:
model = models.Book
fields = "__all__"

在视图中使用序列化器

class TestView(APIView):
def get(self, request, *args, **kwargs):
queryset = models.Book.objects.all()
serializer = serializers.BookSerializers(queryset, many=True, fields=("id", "title", "price"))
# fields: 指定要序列化的字段
return Response(serializer.data)

自定义field

虽然内置有很多的字段类型, 但是从实际的开发角度来说, 内置的都是一些普遍使用的字段, 再生产环境中结合实际问题, 那就需要我们自己定义字段了

现在就有一种实际需求

公司购买了多台CDN服务器, 从来存放图片等静态资源, 现在有一个问题, 假如某一天公司换了CDN, 那么之前代码中的图片链接都要修改一遍吗, 肯定不行

其实解决这个问题的方法有多种, 下面就使用自定义字段来解决这个问题

1. 创建一个自定义字段

class ImagePathField(fields.Field):

    def __init__(self, cdn_host, *args, **kwargs):
super(ImagePathField, self).__init__(*args, **kwargs) self.cdn_host = cdn_host # 封装CDN主机 def to_representation(self, value):
"""
序列化时这个方法会被执行
:param value:
:return:
"""
return "{}/{}".format(self.cdn_host, value) # 构建完整的链接地址, 返回值将作为数据源 def to_internal_value(self, data):
pass

2. 在序列化器中使用自定义的字段

class BookSerializers(DynamicFieldsModelSerializer):
title = fields.ImagePathField(settings.CND_HOST) # 使用自定义的字段, 还可以传递source参数, 就相当于执行ORM, 写什么就对这个对象"."什么 class Meta:
model = models.Book
fields = "__all__"

3. 验证序列化结果

方法字段

除了上面的自定义字段, 还有一种方法字段方法字段, 这种字段也能够起到自定义的效果

1. 在序列化器中使用方法字段

class BookSerializers(DynamicFieldsModelSerializer):
authors = serializers.SerializerMethodField() # 使用方法字段 class Meta:
model = models.Book
fields = "__all__" def get_authors(self, value):
"""
对authors这个字段进行序列化时, 会调用get_字段这个方法, 这个方法的返回值将作为数据源
:param value:
:return:
"""
author_str = ""
for author in value.authors.all():
author_str += "%s-%s " % (author.name, str(author.age))
return author_str

2. 在视图中对数据进行序列化

class TestView(APIView):
def get(self, request, *args, **kwargs):
queryset = models.Book.objects.all()
serializer = serializers.BookSerializers(queryset, many=True, fields=("id", "title", "price", "authors"))
# fields: 指定要序列化的字段
return Response(serializer.data)

3. 验证序列化结果

内置的时间字段 DateTimeField

在处理时间数据时, 让人头疼就是时间的格式, 不同的位置可能显示的格式不一样, 在DRF中内置了时间字段, 可以对时间数据做格式化

1. 在序列化器中使用时间字段

class BookSerializers(DynamicFieldsModelSerializer):
pub_date = serializers.DateTimeField(format="%Y-%m-%d %X") # 使用时间字段, 指定时间格式 class Meta:
model = models.Book
fields = "__all__"

2. 验证序列化结果

内置字符串字段  CharField

字符串是用的最多的数据类型, 当你需要从一个ORM对象关联的另外一种表中取某某一个字段时, 那么你就可以使用CharField

1. 在序列器中使用CharField

很重要的一个参数就是source, 他可以执行ORM操作

还有一个参数就会default, 可以给一个默认值

class BookSerializers(DynamicFieldsModelSerializer):
publish = serializers.CharField(source="publish.address") # source默认就是publish, 不需要写, 使用"."的方式进行ORM操作 class Meta:
model = models.Book
fields = "__all__"

2. 验证序列化结果

嵌套的序列化器

当表结构很深的时候, 构建数据往往是很麻烦的事情, 而且考虑到网络传输的效率问题, 还要尽量的减少无用的数据传输, 只传输必须的数据

这样一来就需要在序列化的时候下功夫了.

ORM有外键和多对多, 一对一等数据类型, 对比着序列化器, 就是序列化一个元素, 序列化多个元素而已

下面是我在调查问卷系统中的一个嵌套的序列化器

class ChoicesSerializer(DynamicFieldsModelSerializer):
"""
4. 用于获取问题所对应的选项的答案和答案所对应的分值的序列化器
""" class Meta:
model = models.SurveyChoices
fields = "__all__" class QuestionSerializer(DynamicFieldsModelSerializer):
"""
3. 获取问卷调查模板的所有问题
"""
survey = serializers.SerializerMethodField()
survey_item = serializers.IntegerField(source="pk")
choices = ChoicesSerializer(source="answers", many=True, fields=("content", "points")) # fields: 指定要序列化的字段
value = serializers.CharField(default="")
error = serializers.CharField(default="") class Meta:
model = models.SurveyItem
fields = (
"survey", # 问题所属的调查问卷模板id
"survey_item", # 问题的id
"name", # 问题内容
"answer_type", # 问题的类型
"choices", # 如果是选择题, 对应的选项
"value", # 答案
"error", # 用作于提示的错误信息
) def get_survey(self, instance):
""" :param instance:
:return:
"""
return self.context.get("survey_id") class SurveysSerializers(DynamicFieldsModelSerializer):
"""
2. 获取调查问卷使用的问卷模板
"""
questions = serializers.ListSerializer(child=QuestionSerializer()) class Meta:
model = models.Survey
fields = (
"id", # 问卷模板的id
"name", # 问卷模板的名称
"questions", # 该问卷模板关联的所有问题
) def to_representation(self, instance):
""" :param instance:
:return:
"""
self.context["survey_id"] = instance.pk data = super(SurveysSerializers, self).to_representation(instance) return data class GetQuestionnaireDetailSerializers(DynamicFieldsModelSerializer):
"""
1. 获取调查问卷详情页的序列化器的入口
"""
surveys = SurveysSerializers(many=True) class Meta:
model = models.MiddleSurvey
fields = (
"name", # 调查表的名字
"surveys", # 本次调查表使用的所有问题模板
)

看着代码挺多, 其实套路都是一样

当要序列化的字段是一个外键关系时, 就给这个字段指定另外一个序列化器,

如果是多对多, 那么序列化器中就需要指定many=True, 否则就不用.

和正常的使用序列化器一样

上面说的是序列化, 还有反序列化, 同样可以使用嵌套序列化器

djangorestframework怎么这么好用!的更多相关文章

  1. 15.django之Django-Rest-Framework

    1.首先安装Django-Rest-Framework pip3 install djangorestframework pip3 install markdown Markdown为可视化 API ...

  2. 【Python】djangorestframework 基于django框架的接口开发

    官网:http://www.django-rest-framework.org/#installation 下载:https://pypi.python.org/pypi/djangorestfram ...

  3. 阅读{django-restframework}源码[generics.py]学习笔记

    首先django-restframework是基于django的一个框架.   mixins.py中开头是这样写的: Basic building blocks for generic class b ...

  4. python 运行python manege.py runserver时报错:“no module named djangorestframework” 的解决方案

    python 运行python manege.py runserver时报错:“no module named djangorestframework” 的解决方案 importerror:no mo ...

  5. Django-Rest-Framework 教程: 快速入门

    本篇中, 我们会创建一个简单的API, 用来查看和编辑django默认的user和group数据. 1. 设置 我们创建django项目tutorial, 和app quickstart: # 创建新 ...

  6. django-rest-framework 快速开始

    搭建项目 # Set up a new project django-admin.py startproject tutorial cd tutorial # Create a virtualenv ...

  7. 初次就这么给了你(Django-rest-framework)

    Django-Rest-Framework Django-Rest框架是构建Web API强大而灵活的工具包. 简单粗暴,直奔主题. pip install django pip install dj ...

  8. django-rest-framework之序列化

    前言:昨天学习了rest-framework序列化方面的知识,故写了博客记录一下.官网:http://www.django-rest-framework.org/tutorial/1-serializ ...

  9. django-rest-framework之请求与响应

    前言:在上一篇文章,已经实现了访问指定URL就返回了指定的数据,这也体现了RESTful API的一个理念,每一个URL代表着一个资源.当然我们还知道RESTful API的另一个特性就是,发送不同的 ...

  10. django-rest-framework快速入门

    前言:第一次接触django-rest-framework是在实习的时候.当时也不懂,看到视图用类方法写的感觉很牛逼的样子.因为官网是英文的,这对我的学习还是有一点的阻力的,所以当时也没怎么学.真是太 ...

随机推荐

  1. Highcharts error #14: www.highcharts.com/errors/14

    错误原因:数据类型错误,需要的是Number类型,传入的却是String 以为为官网说明: Highcharts Error #14 String value sent to series.data, ...

  2. struts1.3.10 和 hibernate 3.3.2 一起加载时 出现javax.servlet.ServletException: java.lang.NoSuchMethodError: antlr.collections.A 错误

    struts1.3.10 需要导入一个 antlr-2.7.2.jar 的jar包: hibernate 3.3.2 需要导入一个 antlr-2.7.6.jar 的jar包,这两个包有冲突,所以需要 ...

  3. C++字符分割

    AfxExtractSubString 表头: <afxwin.h> BOOL AFXAPI AfxExtractSubString ( CString& rString, LPC ...

  4. SVN学习——简单入门之创建仓库、导入、检出(一)

    从刚刚参加工作就开始使用svn,清晰的记得那年师姐比较生气的来找我:“你怎么又不更新就提交代码了,把我写的都给覆盖掉了”,哈哈~ 虽然一直在用svn,不过在日常工作中主要用到的是简单的操作,而且大多数 ...

  5. java面试题之 -----面向切面编程

    这种在运行时,动态地将代码切入到类的指定方法.指定位置上的编程思想就是面向切面的编程. 面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是 ...

  6. java面试题----工厂模式大整理(面试问的较多)

    在一次面试中了解到工厂模式在实际应用中的重要性,可以说工厂模式的应用随处可见,以下是百度百科对工厂模式的介绍 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式.著名的Jiv ...

  7. elenium2学习(十六)-- 富文本(自动发帖)

    前言 富文本编辑框是做web自动化最常见的场景,有很多小伙伴遇到了不知道无从下手,本篇以博客园的编辑器为例,解决如何定位富文本,输入文本内容 一.加载配置 1.打开博客园写随笔,首先需要登录,这里为了 ...

  8. 防止HTML出现滚动条时页面的抖动

    <html> <style> * { padding: 0; margin: 0; } body { font: 40px fantasy; } .container { wi ...

  9. WPF产生不重复的随机数

    WPF产生不重复的随机数 在给定的区间范围(比如[50,99]),产生给定数量的随机数(不如10个),要求产生的随机数不重复首先给定变量min=50;max=99+1;//习惯与程序规定的编码不同所致 ...

  10. Android(java)学习笔记26:File类的使用

    1. File类的使用  package cn.itcast_01; import java.io.File; /* * 我们要想实现IO的操作,就必须知道硬盘上文件的表现形式. * 而Java就提供 ...