restful协议中,一切皆是资源,操作只是请求方式

model_to_dict()方法:

from django.forms.models import model_to_dict
obj = Publish.objects.filter(pk=1).first()
model_to_dict(obj) # model_to_dict(对象)是Django的一个方法:返回一个字典,key是obj 这个对象的字段名,value是字段对应的值

restframework 下的 APIView:

# APIView流程:
1.re_path(r"^book/$",views.BookView.as_view(),name="books"), # 最终执行的是View下的view
2."book/"一旦被访问,view(request)执行 # 此时是旧的 request(原生的) <=======>等同于 view(request)执行的是 APIView这个类下的 dispatch() <=====> 请求方式对应的实例方法 3.dispatch():
     # 包含初始化操作 initial() (初始化后的request都是新的request)
构建新的request对象:
self.request = Request(request)
self.request._request # 可得到旧的request
self.request.GET # 获取GET请求数据
self.request.data # 获取POST、PUT请求数据 (不用 self.request.POST的原因:.POST只能获取到 urlencoded 这个类型的请求数据) 4. 做分发:
如 GET请求:--- self.get(self,request)方法 # 此时是新的request # 原生的request(Django提供)支持的操作:
request.body # 请求体里面的原生数据
request.POST
... from rest_framework.views import APIView
# 新的request()支持的操作:
request._request # Django提供的原生的request,可 request._request.POST 等操作
request.data # 所有的请求数据(POST请求);已经反序列化后的结果
request.GET # 新的request也有 .GET的方法,相当于 request._request.GET

serializers.serialize(数据类型,QuerySet):将QuerySet序列化(Django方法)

# serializers是Django提供的一个方法,不属于 restful
from django.core import serializers
publish_list = Publish.objects.all()
ret = serializers.serialize("json",publish_list) # 将 publish_list这个queryset 序列化为 json格式的数据模型

serializers.Serializer (instance=,many=): 为QuerySet和model对象做序列化(REST方法)

# 这是restframework 提供的一个方法:
from rest_framework import serializers
book_list = Book.objects.all() class BookSerializers(serializers.Serializer): # 先创建一个序列化的类;语法 类似于 Form
title = serializers.CharField()
price = serializers.IntegerField() # 列出需要序列化出来的字段
publish = serializers.CharField(source="publish.name") # source="publish.name" 表示 取的是 publish表中的name字段 #(publish是一对多字段)
# authors = serializers.CharField(source="authors.all") # (authors是多对多字段) # 多对多时, source 可以 .all(一个方法)
authors = serializers.SerializerMethodField() # serializers.SerializerMethodField() 专门用于 多对多 字段;下面要有 get_authors方法
def get_authors(self,obj):
temp = []
for i in obj.authors.all():
temp.append(i.name)
return temp # 用上面创建出来的类对 publish_list 这个QuerySet 进行实例化
bs = BookhSerializers(publish_list,many=True) # many=True 表示序列化的是一个QuerySet;其还可以序列化 model对象
bs.data # 获取序列化后的一个列表套字典的形式(QuerySet;model对象就返回一个字典) """
BookhSerializers(instance=publish_list,many=True)序列化的实现原理:
temp = []
for obj in publish_list:
temp.append(
{
"title":obj.title,
"price": obj.price,
"publish": obj.publish.name # 有 source="publish.name" 时的情况 # 没有source="publish.name"时,是:"publish":obj.publish, (即会显示关联表中的 __str__方法)
# "authors": obj.authors.all() # 有 source="authors.all"时,返回的是一个 QuerySet
"authors": get_authors(obj) # SerializerMethodField() 情况下,"authors"字段对应的值 只取决于 get_authors方法的返回值
}
) 如果 obj中有 关联字段,则 "关联字段": str(obj.关联字段) (即 显示关联表中的 __str__方法)
"""

注:django_restframework 的 Serializer 和 ModelSerializer 返回给前端数据时,会在 ImageField 和 FileField 字段的路径前面自动加上 "/media/"(根据settings中的media配置),但 django的 Serializer 返回给前端数据时,不会在 ImageField 和 FileField 的路径前端加上 "/media/",这也是 django_restframework Serializer和ModelSerializer的完善之处。

REST 的 Serializer 需要自己写 create() 和 update() 方法。

serializers.ModelSerializer:  # 语法类似于ModelForm # 可以直接对接数据库

class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__" # 在mixins.CreateModelMixin中,ModelSerializer校验完成后,会拿着 fields 中的字段做序列化(序列化的目的是返回给前端);如果 fields中的某个字段不需要序列化(如 该字段也已经被你删除了),则可以把该字段设置为 write_only=True # 多对多字段序列化时,默认得到的是一个列表,列表中是 所有对象的pk值 # 自定制关联字段的序列化
   # one2one/fk/choice字段:
publish = serializers.CharField(source="publish.name")   # m2m字段:
authors = serializers.SerializerMethodField() # 自定义字段名要用在下面的 get_自定义字段() 这个方面中
def get_authors(self,obj): # get_m2m自定义字段()
temp = []
for i in obj.authors.all():
temp.append(i.name)
return temp
"""
如果没有自定制,默认用 ModelSerializer 自己的;
   如果想 跨表 获取 choices 字段(假如为:city)的中文信息,可利用自定义字段的方式如: city = serializers.CharField(source="publish.get_city_display") # source 中的 publish.get_city_display 后面不用加 ();
   非跨表的 choices 字段, 直接是 source="get_xx_display"
""" """
restframework下的序列类 ModelSerializer:
1.将QuerySet或者 一个model对象序列化成Json数据
2.做数据校验
3.json数据 转成 QuerySet/model对象,如:
def post(self,request):
bs = BookModelSerializer(data=request.data)
if bs.is_valid(): # 做校验
bs.save() # .save() 就是 create()方法 # 此时 json数据---> queryset/model对象 ---> 数据库中的一条记录
return Response(bs.data) """

mixins.CreateModelMixin代码:

Response() 中的 serializer.data 会按照 fields 中的字段序列化

补充:

request.query_params  # 获取到 GET请求数据;request是后来封装好的request
ModelSerializer.initial_data # Django DRF 的 Serializer 和 ModelSerializer 有一个属性 initial_data,前端传过来的数据都放在 initial_data 里面(字典的形式);调用 validate() 之前的数据(字段校验之前的数据) # 在 view 中,可以去 self 中取 request,如:self.request;但在 Serializer 中不能从 self 中取 request,而是要这样取 request : self.context["request"]

序列化示例

开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。

models部分:

from django.db import models

# Create your models here.

class Book(models.Model):
title=models.CharField(max_length=32)
price=models.IntegerField()
pub_date=models.DateField()
publish=models.ForeignKey("Publish")
authors=models.ManyToManyField("Author")
def __str__(self):
return self.title class Publish(models.Model):
name=models.CharField(max_length=32)
email=models.EmailField()
def __str__(self):
return self.name class Author(models.Model):
name=models.CharField(max_length=32)
age=models.IntegerField()
def __str__(self):
return self.name

views部分:

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers # django的 Serializer from rest_framework import serializers # rest_framework 的 Serializer class BookSerializers(serializers.Serializer): # 该示例中 django 和 rest_framework 的 Serializer同时用这一种形式
title=serializers.CharField(max_length=32)
price=serializers.IntegerField()
pub_date=serializers.DateField()
publish=serializers.CharField(source="publish.name")
#authors=serializers.CharField(source="authors.all")
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for author in obj.authors.all():
temp.append(author.name)
return temp class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
# 序列化方式1:
# from django.forms.models import model_to_dict
# import json
# data=[]
# for obj in book_list:
# data.append(model_to_dict(obj))
# print(data)
# return HttpResponse("ok") # 序列化方式2:
# data=serializers.serialize("json",book_list)
# return HttpResponse(data) # 序列化方式3:
bs=BookSerializers(instance=book_list,many=True)
return Response(bs.data) # 序列化后都要把 bs.data 的数据返回

ModelSerializer

class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"

提交的POST请求

def post(self,request,*args,**kwargs):

        bs=BookSerializers(data=request.data,many=False)
if bs.is_valid(): # 做校验
# print(bs.validated_data)
bs.save() # 把数据保存到数据库中(会有反序列化操作) # .save()中有 create()方法,即 save()会调用 create() 方法
return Response(bs.data)
else:
return HttpResponse(bs.errors) # bs.errors 表示 错误信息

重写save()中的create()方法

class BookSerializers(serializers.ModelSerializer):

      class Meta:
model=Book
fields="__all__"
# exclude = ['authors',]
# depth=1 # 添加多对多字段时需要重写 save()中的 create()方法
def create(self, validated_data): authors = validated_data.pop('authors') # 返回 authors(多对多字段) 并返回
obj = Book.objects.create(**validated_data) # 添加非多对多字段
obj.authors.add(*authors) # 在第三张表中添加authors
return obj

单条数据的GET和PUT请求

class BookDetailViewSet(APIView):

    def get(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj) # 把查到的 记录obj 序列化后返回给用户
return Response(bs.data) def put(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj,data=request.data) # Serializer(要修改的记录对象,data=需要更新的数据) # 更新操作
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)

超链接API:Hyperlinked

class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__" # 让 publish 字段获取到的值为其对应的一个 url
publish= serializers.HyperlinkedIdentityField(
view_name='publish_detail', # 别名是“publish_detail”的url
lookup_field="publish_id", # 需要查询的字段
lookup_url_kwarg="pk") # url中为“pk”的有名分组 # 有 HyperlinkedIdentityField 时, 需要在 序列化类实例化时 添加 "context={'request',request}"

urls部分:

 urlpatterns = [
url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]

rest_framework 的 Serializer 和 ModelSerialzer 可参考: https://blog.csdn.net/FightFightFight/article/details/80059024

HiddenField字段:

class UserFavSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
) # HiddenField 的值不需要用户自己post数据过来,也不会显示返回给用户;配合 CurrentUserDefault() 可以实现自动获取到当前用户 class Meta:
model = UserFav
fields = ("user","goods","id") # 如果此处还需要一个删除功能,则 fields 里面还需要加上 "id",从而创建之后也把 id 返回给前端

DRF Serializer 详细用法可参考:https://blog.csdn.net/l_vip/article/details/79156113

DRF Serializer 的 验证

1.字段级别的验证

你可以通过向你的Serializer子类中添加 .validate_<field_name> 方法来指定自定义字段级别的验证。这些类似于Django表单中的.clean_<field_name>方法。

这些方法采用单个参数,即需要验证的字段值。

你的validate_<field_name>方法应该返回 一个验证过的数据 或者 抛出一个serializers.ValidationError异常。例如:

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
title = serializers.CharField(max_length=100)
content = serializers.CharField() def validate_title(self, value):
"""
Check that the blog post is about Django.
"""
if 'django' not in value.lower():
raise serializers.ValidationError("Blog post is not about Django")
return value

注意: 如果你在序列化器中声明<field_name>的时候带有required=False参数,字段不被包含的时候这个验证步骤就不会执行。

2. 对象级别的验证

要执行需要访问多个字段的任何其他验证,请添加一个 .validate() 方法到你的Serializer子类中。这个方法采用字段值字典的单个参数,如果需要应该抛出一个 ValidationError异常,或者知识返回经过验证的值。例如

from rest_framework import serializers

class EventSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
start = serializers.DateTimeField()
finish = serializers.DateTimeField() def validate(self, data):
"""
Check that the start is before the stop.
"""
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return data

DRF ModelSerializer 保存密码的方法:

# ModelSerializer 在 保存前端传过来的数据时(.save()方法),是直接把这些数据保存到数据库的;这时保存到数据库的密码也是明文的,为了将密码保存为密文的,则需要重构 .save()方法 调用的 create() 方法

from rest_framework import serializers
from rest_framework.validators import UniqueValidator # 验证字段的值唯一 class UserRegSerializer(serializers.ModelSerializer):
"""用户注册"""
code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, label="验证码",
error_messages={
"blank": "请输入验证码",
"max_length": "验证码格式错误",
"min_length": "验证码格式错误"
},
help_text="验证码") # write_only=True 表示 只写模式,即只能反序列化,不能序列化、发送给前端
username = serializers.CharField(label="用户名",required=True,allow_blank=False,help_text="用户名",
validators=[UniqueValidator(queryset=UserInfo.objects.all(),message="用户已经存在")]) # validators 表示验证器;UniqueValidator 用于验证字段的值唯一 password = serializers.CharField(
style={"input_type":"password"},help_text="密码",label="密码",write_only=True
) # style={"input_type":"password"} 用于说明该字段是 password 的类型(前端输入的时候会隐藏);write_only=True 不能返回给前端 # 重构 create() 方法,让密码以密文保存
def create(self, validated_data):
user = super(UserRegSerializer, self).create(validated_data)
user.set_password(validated_data["password"]) # 重置密码
user.save()
return user class Meta:
model = UserInfo
fields = ("username","code","mobile","password") # code 和 password 这两个字段不会发送给前端(由于 write_only )

restful(1):序列化的更多相关文章

  1. Restful 3 -- 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...

  2. SrpingMVC/SpringBoot中restful接口序列化json的时候使用Jackson将空字段,空字符串不传递给前端

    笔者的JSON如下: { "code": 10001, "message": "成功", "nextUrl": null ...

  3. 在django restful framework中设置django model的property

    众所周知,在django的model中,可以某些字段设置@property和setter deleter getter,这样就可以在存入数据的时候进行一些操作,具体原理请参见廖雪峰大神的博客https ...

  4. django restful framework 一对多方向更新数据库

    目录 django restful framework 序列化 一 . 数据模型: models 二. 序列化: serializers 三, 视图: views 四, 路由: urls 五. 测试 ...

  5. rest-framwork官方文档教程(一)

    该项目是按照官网quickstart进行的,具体也可查看rest-framework官网: https://www.django-rest-framework.org/tutorial/quickst ...

  6. Django编写RESTful API(一):序列化

    欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...

  7. python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)

    昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...

  8. rest-framework 序列化格式Restful API设计规范

    理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...

  9. RESTful API终极版序列化封装

    urls: from django.conf.urls import url from app01 import views urlpatterns = [ # url(r"comment/ ...

随机推荐

  1. jmeter(十)JMeter 命令行(非GUI)模式

    前文 讲述了JMeter分布式运行脚本,以更好的达到预设的性能测试(并发)场景.同时,在前文的第一章节中也提到了 JMeter 命令行(非GUI)模式,那么此文就继续前文,针对 JMeter 的命令行 ...

  2. VMware虚拟机中涉及的3种常见网络模式

    桥接模式.这种模式下,虚拟机和物理机连的是同一个网络,虚拟机和物理机是并列关系,地位是相当的.比如你家如果有用路由器,那么你的电脑和你的手机同时连接这个路由器提供的Wi-Fi,那么它们的关系就是这种模 ...

  3. 10.3 Implementing pointers and objects and 10.4 Representing rooted trees

    Algorithms 10.3 Implementing pointers and  objects  and 10.4 Representing rooted trees Allocating an ...

  4. vscode增加xdebug扩展

    首先确保php增加了xdebug扩展,方法很多,可参考 https://www.cnblogs.com/wanghaokun/p/9084188.html.可通过phpinfo()查看是否已开启支持. ...

  5. Farseer.net轻量级开源框架说明及链接索引

    Farseer.net是什么? 基于.net framework 4 开发的一系列解决方案. 完全开源在GitHub中托管.并发布到NuGet中. Farseer.Net由最初的关系数据库ORM框架后 ...

  6. Spring Boot(15)——自动配置Validation

    自动配置Validation当应用中的Classpath下存在javax.validation的实现时,Spring Boot的org.springframework.boot.autoconfigu ...

  7. Java 类执行顺序

    1.如果父类有静态成员赋值或者静态初始化块,执行静态成员赋值和静态初始化块2.如果类有静态成员赋值或者静态初始化块,执行静态成员赋值和静态初始化块3.将类的成员赋予初值(原始类型的成员的值为规定值,例 ...

  8. 10 Steps To be a senior programmer

    What 软件工程师的职业生涯要历经以下几个阶段:初级.中级,最后才是高级.这篇文章主要是讲如何通过 10 个步骤助你成为一名高级软件工程师. Why 得到更多的报酬!因为你的薪水会随着你水平的提高而 ...

  9. Poi 写入图片进入excel

    public static void cacheWritePicture(BufferedImage bufferImg, Sheet sheet, Workbook wb, int width, i ...

  10. Oracle数据库自定义函数练习20181031

    --测试函数3 CREATE OR REPLACE FUNCTION FN_TEST3 (NUM IN VARCHAR2) RETURN VARCHAR2 IS TYPE VARCHAR2_ARR ) ...