使用drf的序列化类实现增删改查接口

Posted smyz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用drf的序列化类实现增删改查接口相关的知识,希望对你有一定的参考价值。

什么是DRF

drf全称:django rest framework,它可以帮助我们快速的实现符合restful规范的接口。

安装DRF

pip3 install djangorestframework
# 注意:如果django版本过低,安装完drf后,会被重装为最新版本,此时,再手工重新安装django即可。

基于原生创建五个接口

  • urls.py
from app01 import views

urlpatterns = [
    path(\'admin/\', admin.site.urls),
    path(\'api/v1/books/\', views.BookView.as_view()),
    path(\'api/v1/books/<int:pk>/\', views.BookDetailView.as_view()),
]
  • models.py
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)
  • views.py
from django import views
from app01 import models
from django.http import JsonResponse


# Create your views here.
class BookView(views.View):
    def get(self, request):
        # 查询出所有图书
        books = models.Book.objects.all()
        book_list = []

        for book in books:
            book_list.append(\'name\': book.name, \'price\': book.price, \'publish\': book.publish)
        return JsonResponse(book_list, safe=False)

    def post(self, request):
        # 获取前端传入的数据
        name = request.POST.get(\'name\')
        price = request.POST.get(\'price\')
        publish = request.POST.get(\'publish\')
        # 将数据写入到数据库
        book = models.Book.objects.create(name=name, price=price, publish=publish)
        # 返回给前端新增的对象
        return JsonResponse(\'name\': book.name, \'price\': book.price, \'publish\': book.publish)


class BookDetailView(views.View):
    # 查询一条数据
    def get(self, request, pk):
        book = models.Book.objects.filter(pk=pk).first()
        return JsonResponse(\'id\': book.pk, \'name\': book.name, \'price\': book.price, \'publish\': book.publish)
    # 修改一条数据
    def post(self, request, pk):
        # 找到要修改的数据
        book = models.Book.objects.filter(pk=pk).first()
        # 获取前端传入的数据,进行修改
        book.name = request.POST.get(\'name\')
        book.price = request.POST.get(\'price\')
        book.publish = request.POST.get(\'publish\')
        book.save()
        # 返回给前端修改后的数据
        return JsonResponse(\'id\': book.pk, \'name\': book.name, \'price\': book.price, \'publish\': book.publish)

    # 删除一条
    def delete(self, request, pk):
        book = models.Book.objects.filter(pk=pk).delete()
        return JsonResponse(data=\'\')

基于rest_framework的增删改查

查询多条数据

流程

  1. 需要在models.py创建测试使用的表
  2. 要使用rest_framework的serializers,需要先在应用中创建serializer.py(名字随意起),并在里面创建序列化类,有点类似于django的form组件。
  3. 在views中引入创建的serialzer中的序列化类,在创建类的时候使用

创建表

  • models.py
# 创建表
from django.db import models


# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)

创建序列化类

  • serializer.py
from rest_framework import serializers
from app01 import models


class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

创建视图类

  • views.py
from app01 import models
from app01.serializer.serializer import BookSerializer
from rest_framework.views import APIView, Response
class BookView(APIView):
    # 查询多条数据
    def get(self, request):
        books = models.Book.objects.all()
        # instance是要序列化的对象  # many参数默认为None,如果返回结果是queryset,就需要指定many=True
        ser = BookSerializer(instance=books, many=True)
        return Response(ser.data)

增加路由

  • urls.py
path(\'api/v1/books/\', views.BookView.as_view()),

查询单条数据

序列化类不变

  • serializer.py
from rest_framework import serializers
from app01 import models


class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

视图类定义对象

  • views.py
class BookDetailView(APIView):
    # 序列化单条数据
    def get(self, request, *args, **kwargs):
        # 根据传入的数据,进行筛选
        book = models.Book.objects.filter(pk=kwargs.get(\'pk\')).first()
        # 序列化
        ser = BookSerializer(instance=book)
        return Response(ser.data)

新增路由

  • urls.py
path(\'api/v1/books/<int:pk>/\', views.BookDetailView.as_view()),

新增一条数据

序列化类

  • 新增一条数据,需要在序列化类中定义create方法
  • serializer.py
class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()
    # 新增一条数据,需要在序列化类中定义create方法
    def create(self, validated_data):
        book = models.Book.objects.create(**validated_data)
        return book

视图类

  • views.py
class BookView(APIView):
    # 新增一条数据
    def post(self, request):
        # 把前端传入的要保存的数据,传给data参数
        ser = BookSerializer(data=request.data)
        # 校验数据
        if ser.is_valid():
            # 如果校验通过,则保存数据
            # 如果要保存数据,需要在序列化类中增加create方法
            ser.save()
            return Response(\'code\': 100, \'msg\': \'新增成功\', \'result\': ser.data)
        else:
            return Response(\'code\': 101, \'msg\': ser.errors)

修改一条数据

  • 修改一条数据,需要在序列化类中定义update方法
  • serializer.py
class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    def update(self, instance, validated_data):
        # instance是要修改的对象
        # validated_data是校验过后的数据
        instance.name = validated_data.get(\'name\')
        instance.price = validated_data.get(\'price\')
        instance.publish = validated_data.get(\'publish\')
        # 保存修改的数据
        instance.save()
        # 返回修改后的数据
        return instance

视图类

  • views.py
class BookDetailView(APIView):
    # 反序列化  修改数据
    def put(self, request, pk):
        book = models.Book.objects.filter(pk=pk).first()
        # 使用data接收前端传过来的数据,使用instance指定要修改哪个
        ser = BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(\'code\': 100, \'msg\': \'修改成功\', \'result\': ser.data)
        else:
            return Response(\'code\': 101, \'msg\': ser.errors)

删除一条数据

  • 删除数据只需要在视图类中定义即可
  • views.py
class BookDetailView(APIView):
    def delete(self, request, pk):
        models.Book.objects.filter(pk=pk).delete()
        return Response(\'code\': 100, \'msg\': \'删除成功\')

序列化之钩子函数校验

局部钩子

  • 需要导入ValidationError方法
  • 只需要定义以 “validate_字段名” 命名的函数即可,如下
from rest_framework import serializers
from app01 import models
from rest_framework.exceptions import ValidationError

class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    def create(self, validated_data):
        book = models.Book.objects.create(**validated_data)
        return book

    def update(self, instance, validated_data):
        # instance是要修改的对象
        # validated_data是校验过后的数据
        instance.name = validated_data.get(\'name\')
        instance.price = validated_data.get(\'price\')
        instance.publish = validated_data.get(\'publish\')
        # 保存修改的数据
        instance.save()
        # 返回修改后的数据
        return instance

    # 局部钩子
    def validate_name(self, name):
        # 校验name是否合法,比如name不能等于123
        if name == \'123\':
            # 校验不合法,直接抛异常
            raise ValidationError(\'不可以为123\')
        else:
            return name

报错如下:

全局钩子

  • 全局钩子只需要定义validate函数即可,如下
from rest_framework import serializers
from app01 import models
from rest_framework.exceptions import ValidationError

class BookSerializer(serializers.Serializer):
    # 序列化某些字段(内容写要序列化的字段)
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    def create(self, validated_data):
        book = models.Book.objects.create(**validated_data)
        return book

    def update(self, instance, validated_data):
        # instance是要修改的对象
        # validated_data是校验过后的数据
        instance.name = validated_data.get(\'name\')
        instance.price = validated_data.get(\'price\')
        instance.publish = validated_data.get(\'publish\')
        # 保存修改的数据
        instance.save()
        # 返回修改后的数据
        return instance

    # 局部钩子
    def validate_name(self, name):
        # 校验name是否合法,比如name不能等于123
        if name == \'123\':
            # 校验不合法
            raise ValidationError(\'不可以为123\')
        else:
            return name

    # 全局钩子
    def validate(self, attrs):
        # 校验数据,出版社不能为“我是出版社”
        if attrs.get(\'publish\') == \'我是出版社\':
            raise ValidationError(\'出版社不可以为“我是出版社”\')
        else:
            return attrs

报错如下:

RESTFramework(DRF)框架初探以及认识serializers序列化器的增删改查

定义
Django REST framework (简称 DRF) 是一个强大灵活的wb api工具 功能完善,可快速开发api平台
官网地址

https://www.django-rest-framework.org/

安装要求

pip3 install django==3.2
pip3 install djangorestframework

1.0 使用drf实现用户的增删改查

1.创建app
2.定义数据模型并同步数据库
3.编写序列化器文件
4.编写视图
5.添加api路由

1.1修改settings.py文件

1.2 创建一个app

python3  manage.py startapp myapp_api

1.3 定义数据模型并同步(models.py)

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=30)
    city = models.CharField(max_length=30)
    sex = models.CharField(max_length=30)
    age = models.IntegerField()
python3  manage.py makemigrations  #同步数据
python3  manage.py  migrate    #迁移数据

1.4 编写序列化器文件(serializers.py)

from  myapp_api.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

1.5 编写视图(views.py)

from  rest_framework import viewsets
from .serializers import UserSerializer
from myapp_api.models import User

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()      #指定操作的数据库
    serializer_class = UserSerializer  #指定序列化器

1.6添加路由api

1.6.1 主路由

1.6.2 app路由

from django.urls import path, include
from  myapp_api import views
from rest_framework import routers


#自动注册路由
router = routers.DefaultRouter()
router.register(r'user',views.UserViewSet)

urlpatterns = [
    path('api/', include(router.urls)), #类视图

]

1.7 验证

http://127.0.0.1:8000/myapp_api/api/

post请求验证

get请求验证

put请求验证(更新)更新年龄35

delete请求验证

最终实现数据的增删改查功能!!!

2.0 python 三种常用的序列化方式

2.1 JSON模块

序列化应用场景:用ORM查询数据,采用JSON格式api返回数据
反序列化应用场景:从别的api获取数据,在python里处理

2.2 Django内置的JsonResponse模块

JsonResponse模块自动将pthon对象转化为json对象并响应

缺点: 只能序列化,不支持反序列化,不支持将json对象转化成python对象

2.3 django内置serializers模块

serializers是Django内置的一个序列化器,可直接将python QuerySet对象转化成json格式,但是不支持反序列化。


DRF中有个serializers模块专门负责数据的序列化。
序列化器支持的三种类型:

Serializer: `对Model(数据模型)进行序列化,需自动移字段映射`
ModelSerializer: `对Model(数据模型)进行序列化,会自动生成字段和验证规则,默认包含简单的create()和update()方法`
HyperlinkedModelSerializer: `与ModelSerializer类似,只不过使用超链接来便是关系而不是主键ID`

2.3.1 单独使用 Serializer序列化器实现增删改查

第一步(修改serializers.py文件)

from  myapp_api.models import User
from rest_framework import serializers

class UserSerializer(serializers.Serializer):
    #这里字段必须与使用的模型字段对应
    id = serializers.IntegerField()   
    name = serializers.CharField()
    city = serializers.CharField()
    sex = serializers.CharField()
    age = serializers.IntegerField()

第二步编写视图

from  rest_framework.views  import APIView
from .serializers import UserSerializer
from myapp_api.models import User
from rest_framework.response import Response

class UserView(APIView):
    def get(self,request):
        #获取所有用户
        queryset = User.objects.all()
        #调用序列化器将queryset对象 转化为json
        user_ser = UserSerializer(queryset, many=True)#如果序列化多条数据,需要指定many=True
        # .data是获取序列化结果
        return Response(user_ser.data)
    def post(self,request):
        pass
    def put(self,request):
        pass
    def delete(self,request):
        pass

第三步编写路由

from django.urls import path, re_path
from  myapp_api import views


urlpatterns = [
    re_path('^api/user/$', views.UserView.as_view()),

]

第四步 验证

第五步 查询单用户数据

from  rest_framework.views  import APIView
from .serializers import UserSerializer
from myapp_api.models import User
from rest_framework.response import Response

class UserView(APIView):
    def get(self, request, id=None):
        if id:
            #获取单用户
            obj = User.objects.get(id=id)
            # 调用序列化器将queryset对象 转化为json
            user_ser =UserSerializer(obj)
        else:
            #获取所有用户
            queryset = User.objects.all()
            #调用序列化器将queryset对象 转化为json
            user_ser = UserSerializer(queryset, many=True)#如果序列化多条数据,需要指定many=True
            # .data是获取序列化结果
        return Response(user_ser.data)
    def post(self,request):
        pass
    def put(self,request):
        pass
    def delete(self,request):
        pass

第六步 创建用户

1.0

def post(self,request):
    #调用序列化器将提交的数据进行反序列化
    user_ser = UserSerializer(data=request.data) #request.data是用户提交的post数据
    if user_ser.is_valid():
        #保存数据
        user_ser.save()
        res = 'code': 200, 'msg': '创建用户成功'
    else:
        res = 'code':500, 'msg': '创建用户失败,数据格式不正确'


2.0 在序列化类将数据进行重写


第七步 更新用户数据

7.1 编写serializers.py (更新用户数据,重写数据库)

7.2 编写put更新接口

def put(self,request,id=None):
    obj = User.objects.get(id=id)
    user_ser = UserSerializer(instance=obj,data=request.data)
    if user_ser.is_valid():
        #保存数据
        user_ser.save()
        res = 'code': 200, 'msg': '更新用户成功'
    else:
        res = 'code':500, 'msg': '更新用户失败,数据格式不正确'
    return Response(res)

7.3 测试



异常情况测试,格式不对会直接报错

第八步 编写删除用户的接口

def delete(self,request,id=None):
    obj = User.objects.get(id=id)
    obj.delete()
    res = 'code': 200, 'msg': '删除用户成功!'
    return Response(res)




删除成功

http://127.0.0.1:8000/myapp_api/api/user/

至此,使用serializers序列化器实现了增删改查的api接口编写测试

序列化:视图ORM查询数据库---> 数据产乳序列化器--->从 .data获取数据--->响应前端
反序列化:获取用户提交数据--->数据传入序列化器--->调用.save保存数据(重写create和update方法)

序列化器常用的方法和属性
serializer.is_valid(): 调用序列化器验证是否通过,传入raise_exception=True可以在验证失败时由DRF响应400异常
serializer.errors:获取反序列化器的错误信息
serializer.data: 获取序列化器返回的数据
serializer.save():将验证通过的数据保存到数据库(ORM操作)
完整的接口如下

from  rest_framework.views  import APIView
from .serializers import UserSerializer
from myapp_api.models import User
from rest_framework.response import Response

class UserView(APIView):
    def get(self, request, id=None):
        if id:
            obj = User.objects.get(id=id)  # 获取单用户,调用序列化器将queryset对象 转化为json
            user_ser =UserSerializer(obj)
        else:
            queryset = User.objects.all() ##获取所有用户,调用序列化器将queryset对象 转化为json
            user_ser = UserSerializer(queryset, many=True)#如果序列化多条数据,需要指定many=True
        return Response(user_ser.data)             # .data是获取序列化结果
    def post(self,request):
        user_ser = UserSerializer(data=request.data) #request.data是用户提交的post数据
        if user_ser.is_valid():
            user_ser.save()
            res = 'code': 200, 'msg': '创建用户成功'
        else:
            res = 'code':500, 'msg': '创建用户失败,数据格式不正确'
        return Response(res)

    def put(self,request,id=None):
        obj = User.objects.get(id=id)
        user_ser = UserSerializer(instance=obj,data=request.data)
        if user_ser.is_valid():
            user_ser.save()
            res = 'code': 200, 'msg': '更新用户成功'
        else:
            res = 'code':500, 'msg': '更新用户失败,数据格式不正确'
        return Response(res)

    def delete(self,request,id=None):
        obj = User.objects.get(id=id)
        obj.delete()
        res = 'code': 200, 'msg': '删除用户成功!'
        return Response(res)



name 为空

name 不存在

name字段长度超出规定范围



完整的配置

from  myapp_api.models import User
from rest_framework import serializers

#自定义验证器函数
def  check_sex(data):
    if  data.startswith('男') or data.startswith('女'):
        return data
    else:
        raise serializers.ValidationError('性别必须是男and女')

class UserSerializer(serializers.Serializer):
    #这里字段必须与使用的模型字段对应
    id = serializers.IntegerField(
        read_only=True #仅用于序列化,反序列化忽略
    )
    #针对性返回提示信息
    name = serializers.CharField(
        max_length=20,
        error_messages=
            "blank": '请输入姓名',
            'required': '该字段必填',
            'max_length': '字符长度不超过20'
        
    )
    city = serializers.CharField()
    sex = serializers.CharField(
        validators=[check_sex] #调用验证器函数
    )
    age = serializers.IntegerField(
        min_value=16,
        max_value=100,
        error_messages=
            "blank": '请输入姓名',
            'required': '该字段必填',
            'max_length': '字符长度不超过20',
            'min_value': '年龄不小于16',
            'max_value': '年龄大于100',
        
    )
    def create(self, validated_data):    #validated_data提交的数据,重写,拿到的数据入库
        return User.objects.create(**validated_data)
    def update(self, instance, validated_data):
        return User.objects.filter(id=instance.id).update(**validated_data)  #批量更新

以上配置都在api接口层面进行控制,分别对每一个提交的数据进行控制

更高级用法(使用钩子)
#局部钩子:针对某个字段验证合法性‘validate_字段名’
def  validate_name(self, attrs):
    if attrs.startswith('张'):
        return attrs
    else:
        raise  serializers.ValidationError('姓名必须以张开头')

#全局钩子,针对全局验证合法性
def validated_data(self,attrs):
    from re import findall
    if findall('\\d+', attrs.get('city')):
        raise serializers.ValidationError('城市不能包含数字')
    return attrs




分别对姓名和城市做了具体的限制条件

使用 ModelSerializer 实现增删改查

class  UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = "__all__"


HyperlinkedModelSerualizer序列化器的使用


结果如图所示,id字段编程url字段,自动生成一个链接

总结

DRF序列化器:关联表显示

场景:

一对多:一个项目有多个应用,一个应用只能属于一个项目
多对多:一个应用部署到多台服务器,一个服务器部署多个应用

以上是关于使用drf的序列化类实现增删改查接口的主要内容,如果未能解决你的问题,请参考以下文章

RESTFramework(DRF)框架初探以及认识serializers序列化器的增删改查

python drf 序列化器之数据的增删改查(详细)

多对多表的增删改查与drf的分页

0018 基于DRF框架开发(多表增删改的实现)

mybatis增删改查

使用DbUtils实现增删改查——ResultSetHandler 接口的实现类