python后端之DRF框架(上篇)

一、DRF框架介绍

1、web应用开发模式

1.1、前后端不分离

在这里插入图片描述

1.2、前后端分离

在这里插入图片描述

2、RESTful介绍

RESTful是目前最流行的API设计风格 , REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:

 GET 用来获取资源POST 用来新建资源PUT 用来更新资源(整体更新)PATCH:用来更新资源(局部更新)DELETE 用来删除资源

3、通过操作资源的表现形式来操作资源;
4、资源的形式是XML或者json;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含
理解请求所必需的信息。

3、RESTful API设计风格

3.1、HTTP动词

对于资源的具体操作类型,由HTTP动词表示。常用的HTTP动词有下面四个(括号里是对应的SQL命
令)。

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
DELETE(DELETE):从服务器删除资源。

3.2、url路径

3.2.1 url路径尽量用名词表示,而不用动词
不推荐:

http://api.baidu.com/getProjects
http://api.baidu.com/deleteEnvs

推荐

http:/api.baidu.com/Projects
http:/api.baidu.com/Envs

路径中的project表示操作的资源
3.2.2 不管是单一资源,还是所有资源,路径中名词尽量用复数
不推荐

# 获取单个数据:
GET方法: http://api.baidu.com/Env/1
# 获取所有数据:
GET方法: http://api.baidu.com/allEnvs

推荐

# 获取单个数据:
GET方法: http://api.baidu.com/Envs/1
# 获取所有数据:
GET方法: http://api.baidu.com/Envs

3.3、过滤参数

如果接口需要通过条件过滤返回结果 ,那么过滤的条件参数,应作为查询字符串参数传递。
例如:

?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&size=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。

3.4、返回状态码

客户端的每一次请求,服务器都必须给出回应。回应包括 HTTP 状态码和数据两部分。
HTTP 状态码就是一个三位数,分成五个类别。

 1xx :相关信息2xx :操作成功3xx :重定向4xx :客户端错误5xx :服务器错误

这五大类总共包含100多种状态码,覆盖了绝大部分可能遇到的情况。每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
API 不需要 1xx 状态码,下面介绍其他四类状态码的精确含义。
3.4.1 2XX状态码
200 状态码表示操作成功,restful Api设计风格中,不同的方法可以返回更精确的状态码。

GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content

上面代码中, POST 返回 201 状态码,表示生成了新的资源; DELETE 返回 204 状态码,表示资源已经不存在。
注意点:202 Accepted 状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常
用于异步操作。发生错误时,不应该使用200状态码
3.4.2 4XX状态码
4xx 状态码表示客户端错误,主要有下面几种。

400 Bad Request :服务器不理解客户端的请求,未做任何处理。
401 Unauthorized :用户未提供身份验证凭据,或者没有通过身份验证。
403 Forbidden :用户通过了身份验证,但是不具有访问资源所需的权限。
404 Not Found :所请求的资源不存在,或不可用。
405 Method Not Allowed :用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之
内。
410 Gone :所请求的资源已从这个地址转移,不再可用。
415 Unsupported Media Type :客户端要求的返回格式不支持。比如,API 只能返回 JSON 格
式,但是客户端要求返回 XML 格式。
422 Unprocessable Entity :客户端上传的附件无法处理,导致请求失败。
429 Too Many Requests :客户端的请求次数超过限额。

3.4.3 5XX 状态码
5xx 状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了

500 Internal Server Error :客户端请求有效,服务器处理时发生了意外。
503 Service Unavailable :服务器无法处理请求,一般用于网站维护状态

3.5、返回内容

服务器返回的数据格式,应该尽量使用JSON
针对不同操作,服务器向用户返回的结果应该符合以下规范。

GET /collection:返回资源对象的列表(数组)
GET /collection/1:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/1:返回完整的资源对象
DELETE /collection/1:返回一个空文档

4、DRF框架介绍

在这里插入图片描述
Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。
通常简称为DRF框架 或 REST framework。
DRF框架是建立在Django框架基础之上,由Tom Christie大牛二次开发的开源项目。
特点:

提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
多种身份认证和权限认证方式的支持;
内置了限流系统;
直观的 API web 界面;
可扩展性,插件丰富

DRF(Django REST framework )框架是建立在Django框架基础之上,是一个用于构建Web API 的强大而又灵活的工具,通常简称为DRF框架 或 REST framework。

5、安装和使用

5.1 安装DRF

pip install djangorestframework

5.2 注册rest_framework应用

我们利用在Django框架学习中创建的demo工程,在settings.py的INSTALLED_APPS中添
加’rest_framework’。

INSTALLED_APPS = [
...
'rest_framework',
]

6、Django开发RESTful接口的步骤

1、定义模型类
2、定义路由
3、定义视图

7、DRF开发RESTful接口步骤

1、定义模型类
2、定义序列化器

 作用:进行序列化操作,将ORM对象 转换为json数据进行反序列化,将json数据转换为ORM对象

3、定义路由
4、定义视图

二、序列化器

序列化器的作用

      1、进行数据的校验2、 对数据对象进行转换

1、序列化器的定义

Django REST framework中的序列化器通过类来定义,必须继承rest_framework.serializers.Serializer ,序列化器中的字段和模型类中的字段类型保持一致。
模型类如下:

class UserInfo(models.Model):
name = models.CharField(max_length=20, verbose_name='用户名')
pwd = models.CharField(max_length=18, verbose_name='密码')
email = models.EmailField(max_length=40, verbose_name='邮箱')
age = models.IntegerField(verbose_name='年龄', default=18)

序列化器的定义:

class UserInfoSerializer(serializers.Serializer):
"""用户信息序列化器"""
name = serializers.CharField(help_text='用户信息', max_length=18,
required=True)
pwd = serializers.CharField(help_text='密码', min_length=6,
max_length=18, required=True)
email = serializers.EmailField(help_text='邮箱', required=True)
age = serializers.IntegerField(help_text='年龄', max_value=200,
min_value=0)

2、字段类型与选项介绍

常用字段类型:
在这里插入图片描述
选项参数:
在这里插入图片描述
通用参数:
在这里插入图片描述

3、序列化操作

3.1、环境准备

1、创建项目

django-admin startproject drfdemo1

2、创建应用

python manage.py startapp app1

3、修改setting中的配置

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 注册drf 和新建的应用
"rest_framework",
"app1"
]

4、 model.py 中定义模型类

class UserInfo(models.Model):
name = models.CharField(max_length=20, verbose_name='用户名')
pwd = models.CharField(max_length=18, verbose_name='密码')
email = models.EmailField(max_length=40, verbose_name='邮箱')
age = models.IntegerField(verbose_name='年龄', default=18)
def __str__(self):
return self.name

5、定义序列化器类
在应用中新建文件 serializer.py
在文件 serializer.py 中定义序列化器

from rest_framework import serializers
class UserInfoSerializer(serializers.Serializer):
"""用户信息序列化器"""
name = serializers.CharField(help_text='用户信息', max_length=18,
required=True)
pwd = serializers.CharField(help_text='密码', min_length=6,
max_length=18, required=True)
email = serializers.EmailField(help_text='邮箱', required=True)
age = serializers.IntegerField(help_text='年龄', max_value=200,
min_value=0)

6、激活模型类生成迁移文件、执行迁移文件

# 命令1:生成迁移文件
python manage.py makemigrations
# 命令2:执行迁移文件
python manage.py migrate

7、练习数据准备

# 进行交互环境添加测试数据:python manage.py shell
UserInfo.objects.create(name='张三',pwd='123456',email='123@qq.com',age=19)
UserInfo.objects.create(name='李
四',pwd='123456q',email='1223@qq.com',age=19)
UserInfo.objects.create(name='王
五',pwd='123456q',email='12234@qq.com',age=19)

3.2、序列化操作

序列化 : 将python对象 —> 转换为json格式数据
定义好Serializer类后,如果要通过序列化器类类进行序列化,需要先创建Serializer对象了。
Serializer的参数为:

Serializer(instance=None, data={empty}, **kwarg)
    1)用于序列化时,将模型类对象传入instance参数2)用于反序列化时,将要被反序列化的数据传入data参数

3.2.1、单个数据序列化
进入django交互环境

python manage.py shell

案例

# 通过模型类查询一条用户信息
>>> obj = UserInfo.objects.get(id=1)
# 使用查询到的用户信息,创建一个序列化对象
>>> us = UserInfoSerializer(obj)
>>> us.data
{'name': '张三', 'pwd': '123456', 'email': '123@qq.com', 'age': 19}

3.2.2、查询集序列化

>>> obs = UserInfo.objects.all()
>>> us = UserInfoSerializer(obs,many=True)
>>> us.data
[OrderedDict([('name', '张三'), ('pwd', '123456'), ('email', '123@qq.com'),
('age', 19)]), OrderedDict([('name', '李四'), ('pwd', '123456q'), ('email',
'1223@qq.com'), ('age', 19)]), OrderedDict([('name', '王五'), ('pwd', '123456q'),
('email', '12234@qq.com'), ('age', 19)])]

对多个数据进行序列化加参数:many=True
3.2.3、将序列化得到的数据转换为json

from rest_framework.renderers import JSONRenderer
# 查询用户对象
obj = UserInfo.objects.get(id=1)
# 创建序列化对对象
u = UserInfoSerializer(obj)
# 将得到的字段,转换为json数据
JSONRenderer().render(u.data)

3.3、关联对象嵌套序列化

3.3.1、数据准备
定义模型类

# 模型Addr关联userinfo,
class Addr(models.Model):
user = models.ForeignKey('UserInfo', verbose_name='所属用户',
on_delete=models.CASCADE)
mobile = models.CharField(verbose_name='手机号', max_length=18)
city = models.CharField(verbose_name='城市', max_length=10)
info = models.CharField(verbose_name='详细地址', max_length=200)
def __str__(self):
return self.info

重新生成迁移文件,并执行

# 命令1:生成迁移文件
python manage.py makemigrations
# 命令2:执行迁移文件
python manage.py migrate

添加练习数据

# 通过 python manage.py shell 进入交互环境,添加如下数据
obj = UserInfo.objects.get(id=1)
Addr.objects.create(user=obj,mobile='18898789878',city='长沙',info='湖南省长
沙市岳麓区')
Addr.objects.create(user=obj,mobile='18888889999',city='长沙',info='湖南省长
沙市开福区')

定义序列化器

class AddrSerializer(serializers.Serializer):
"""地址序列化器"""
mobile = serializers.CharField(help_text='手机号', max_length=18)
city = serializers.CharField(help_text='城市', max_length=10)
info = serializers.CharField(help_text='详细地址', max_length=200)
# 关联字段序列化
user = serializers.PrimaryKeyRelatedField()

3.3.2、关联字段序列化的方式
1、PrimaryKeyRelatedField
返回关联字段的id

user = serializers.PrimaryKeyRelatedField()

2、StringRelatedField
返回关联字段模型类 str 方法返回的内容

user = serializers.StringRelatedField()

3、使用关联对象的序列化器
返回关联对象序列化器返回的所有字段

# 关联模型类的序列化器
user = UserInfoSerializer()

4、SlugRelatedField
指定返回关联对象 某个具体字段

# 返回关联对象的name字段
user = serializers.SlugRelatedField(read_only=True,slug_field='name')

3.4、反序列化操作

反序列化 —> 将json格式数据 转换为python对象

在进行反序列化操作是,会先对象数据进行验证,验证通过的情况下再进行保存。
反序列化时,初始化序列化器对象,将要被反序列化的数据传入data参数
3.4.1、数据验证

调用is_valid()方法进行验证,验证成功返回True,否则返回False;
验证成功,可以通过序列化器对象的validated_data属性获取数据;
user1 = {"name":"张三","pwd":"123456","email":"12345453@qq.com","age":18}
ser = UserInfoSerializer(data=user1)
#进行数据校验
ser.is_valid() 
#获取validated_data数据
OrderedDict([('name', '张三'), ('pwd', '123456'), ('email', '12345453@qq.com'), ('age',18)])

注意:is_valid()会根据序列化器中字段对应的约束来进行校验
3.4.2、常用校验字段说明
1、字段长度和是否校验的参数
字段选项参数前面都列出来了,常用的几个字段:

max_length:字段的长度校验
min_length:字段的长度校验
required=False:不需要校验字段是否为空

2、控制序列化和反序列化的字段

read_only = Ture:只参与序列号返回(即序列化),不参与反序列化校验(即反序列化)
write_only = True :只参与反序列化校验,不参与序列号返回

3.4.3、序列化器保存数据
验证通过后,如需保存数据,直接调用序列化器对象的save方法即可,save方法会自动触发序列化器中对应的方法来保存数据

# 反序列化
ser = UserInfoSerializer(data=data)
# 校验数据
ser.is_valid()
# 保存数据
ser.save()

注意点:
保存:sava会调用序列化器中定义 create 方法
更新:sava会调用序列化器中定义 update 方法

3.5、模型序列化器

为了方便我们定义序列化器,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:

基于模型类自动生成一系列字段;
基于模型类自动为Serializer生成validators,比如unique_together;
包含默认的create()和update()的实现;

3.5.1、模型序列化器的使用
定义模型序列化器类,直接继承于serializers.ModelSerializer即可

class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = '__all__'

指定模型类和需要序列化得字段

model 指明参照哪个模型类
fields 指明为模型类的哪些字段生成

3.5.2、指定字段
1、fields
fields = all 代表模型类中得所有字段都进行序列化。
也可以通过fields指定具体字段:

class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
# fields = '__all__' # 所有字段
fields = ('id','age','pwd') # 指定序列化得字段

2、exclude
使用exclude可以明确排除掉哪些字段

class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
exclude = ('id',) # id字段不参与序列化

3、 read_only_fields
通过read_only_fields可以指明只读的字段

class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = '__all__'
read_only_fields = ('id',)

3.5.3、修改字段的参数选项
使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数

class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = '__all__'
extra_kwargs = {
'pwd': {'min_value': 0, 'required': True},
}

3.6、序列化器保存数据案例

前提是模型类要实现create方法和update方法。
使用序列化器新增数据:

data = {"name":"张三","pwd":"9999999","email":"12345453@qq.com","age":18}
ser = UserInfoSerializer(data=data)
# 校验数据
ser.is_valid()
# 保存数据
ser.save()

使用序列化器修改数据:

# 查询对象
user = UserInfo.objects.get(id = 1)
data = {"name":"张三","pwd":"9999999","email":"12345453@qq.com","age":18}
# 创建序列化器
ser = UserInfoSerializer(instance =user ,data=data)
# 校验数据
ser.is_valid()
# 保存数据
ser.save()

3.7、利用序列化器实现增删查改的接口

视图

from django.http import HttpResponse, JsonResponse
from rest_framework.parsers import JSONParser
from .models import UserInfo
from .serializers import UserInfoSerializer
# Create your views here.
def user_list(request):if request.method == 'GET':# 返回用户列表users = UserInfo.objects.all()serializer = UserInfoSerializer(users, many=True)return JsonResponse(serializer.data, safe=False)elif request.method == 'POST':# 添加用户信息data = JSONParser().parse(request)serializer = UserInfoSerializer(data=data)if serializer.is_valid():serializer.save()return JsonResponse(serializer.data, status=201)return JsonResponse(serializer.errors, status=400)
def user_detail(request, id):
"""
获取单个用户、修改用户信息、删除用户信息
"""
try:user = UserInfo.objects.get(id=id)
except UserInfo.DoesNotExist:return HttpResponse(status=404)
if request.method == 'GET':serializer = UserInfoSerializer(user)return JsonResponse(serializer.data)
elif request.method == 'PUT':data = JSONParser().parse(request)serializer = UserInfoSerializer(user, data=data)if serializer.is_valid():serializer.save()return JsonResponse(serializer.data)return JsonResponse(serializer.errors, status=400)
elif request.method == 'DELETE':user.delete()return HttpResponse(status=204)

路由

from django.urls import path
from app1 import views
urlpatterns = [
path('user/', views.user_list),
path('user/<int:id>/', views.user_detail),
]

3.8、自定义验证方法

定义校验方法:

#验证方法名的规范:validate_字段名
class UserInfoSerializer(serializers.Serializer):def validate_pwd(self,value):"""校验逻辑"""

通过validators字段指定验证函数:

def length_validate(value):if not(10<len(value)<20):raise serializers.ValidationError("字段的长度不在10-20之间")
class UserInfoSerializer(serializers.Serializer):pwd = serializers.CharField(validators=length_validate)

三、请求和响应

1、DRF定义视图函数

案例

from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework.response import Response
@api_view(['GET', 'POST'])
def user_list(request):return Response(data={'message':"OK"})
# Django的request
# request.GET # 获取get请求传递的查询参数
# requests.POST # 获取post请求传递的表单参数
# put patch post请求传递的请求体参数(json格式的),Django中并未提供直接获取的方法
params = request.body.denode()
import json
params = json.loads(params)

2、DRF的Request对象

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST
framework提供的扩展了HttpRequest类的Request类的对象。无论前端发送的哪种格式的数据,我们
都可以以统一的方式读取数据。
1、request.data属性
request.data 获取请求体数据。

支持 POST , PUT, PATCH 方法传递的请求体参数
不仅支持表单类型数据,也支持JSON数据,还支持文件数据的获取

2、request.query_params属性
request.query_params获取查询字符串参数的,Django的 request.GET 的作用一样

3、DRF的Response对象

rest_framework.response.Response
REST framework提供了一个响应类 Response ,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

Response(data, status=None, template_name=None, headers=None, content_type=None)

data 不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用 Serializer 序
列化器序列化处理后(转为了Python字典类型)再传递给 data 参数。

3.1 Response参数说明

data : 为响应准备的序列化处理后的数据;
status : 状态码,默认200;
template_name : 模板名称,如果使用 HTMLRenderer 时需指明;
headers : 用于存放响应头信息的字典;
content_type : 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端
所需类型数据来设置该参数

4、响应状态码

在视图中使用数字 HTTP 状态代码并不总是能带来明显的阅读效果,而且如果您输入了错误代码,很容易察觉不到。REST 框架为每个状态代码(如模块中)提供更明确的标识符。 HTTP_400_BAD_REQUEST

from rest_framework import status
status.HTTP_200_OK

5、API 视图的装饰器

REST 框架提供了两个可用于编写 API 视图的包装器。

用于处理基于函数的视图的装饰器。 @api_view
用于处理基于类的视图的类。 APIView

下面我们通过 @api_view 这个装饰器来实现增删查改接口

5.1、使用DRF视图函数完成增删查改

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .serializers import UserInfoSerializer
from .models import UserInfo
# Create your views here.
@api_view(['GET', 'POST'])
def user_list(request):# 判断请求方法:if request.method == 'GET':# 查询所有的用户信息users = UserInfo.objects.all()# 创建序列化器对象ser = UserInfoSerializer(users, many=True)result = {"data": ser.data, 'code': 200, "message": "OK"}return Response(result, status=status.HTTP_200_OK)elif request.method == 'POST':# 获取请求过来的json参数params = request.data# 创建序列化器ser = UserInfoSerializer(data=params)# 校验请求参数if ser.is_valid():# 校验通过,则添加数据到数据库ser.save()return Response({'code': 201, "data": ser.data, "message": "OK"},
status=status.HTTP_201_CREATED)else:return Response({'code': 400, "message": ser.errors},
status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def user_detail(request, id):try:obj = UserInfo.objects.get(id=id)except Exception as e:return Response('404,访问的资源不存在', status=status.HTTP_200_OK)if request.method == 'GET':# 获取单个资源 并返回ser = UserInfoSerializer(obj)return Response({'code': 200, "data": ser.data, "message": "OK"},
status=status.HTTP_200_OK)elif request.method == 'DELETE':# 删除资源obj.delete()return Response(status=status.HTTP_204_NO_CONTENT)elif request.method == 'PUT':ser = UserInfoSerializer(instance=obj, data=request.data)if ser.is_valid():ser.save()return Response({'code': 200, "data": ser.data, "message": "OK"},
status=status.HTTP_200_OK)else:return Response({'code': 400, "message": ser.errors},
status=status.HTTP_400_BAD_REQUEST)

6、使用DRF给url添加后缀

1、修改视图函数
在视图函数后面添加参数 format ,并设置默认值为空

@api_view(['GET', 'POST'])
def user_list(request,format=None)pass
@api_view(['GET', 'PUT', 'DELETE'])
def user_detail(request, id,format=None):pass

2、修改路由配置

from django.urls import path
from . import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('users/', views.user_list),
path('users/<int:id>/', views.user_detail)
]
urlpatterns = format_suffix_patterns(urlpatterns)

3、效果

访问:http://127.0.0.1:8000/app1/users.json,返回json数据
访问 http://127.0.0.1:8000/app1/users.api 访问DRF自带的接口调试页面

7、类视图APIView

DRF中对Django的类视图做了更好的封装,在Django的View的基础上做了更多的功能扩展。接下来一起来学习Django提供的类视图 rest_framework.views.APIView 。

7.1、 APIView 与 View 的区别:

传入到视图方法中的是REST framework的 Request 对象;
视图方法可以返回REST framework的 Response 对象;
任何 APIException 异常都会被捕获到,并且处理成合适的响应信息;
扩展了身份认证、权限检查、流量控制这三个功能。

7.2、扩展的功能(后面讲):

authentication_classes :身份认证
permissoin_classes :权限检查
throttle_classes : 限流

7.3、基于APIView实现增删查改

修改视图

from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import UserInfoSerializer
from .models import UserInfo
class UserListView(APIView):def get(self, request, format=None):users = UserInfo.objects.all()# 创建序列化器对象ser = UserInfoSerializer(users, many=True)result = {"data": ser.data, 'code': 200, "message": "OK"}return Response(result, status=status.HTTP_200_OK)def post(self, request, format=None):params = request.data# 创建序列化器ser = UserInfoSerializer(data=params)# 校验请求参数if ser.is_valid():# 校验通过,则添加数据到数据库ser.save()return Response({'code': 201, "data": ser.data, "message": "OK"},
status=status.HTTP_201_CREATED)else:return Response({'code': 400, "message": ser.errors},
status=status.HTTP_400_BAD_REQUEST)
class UserDetailView(APIView):def get_object(self, id):try:return UserInfo.objects.get(id=id)except UserInfo.DoesNotExist:raise Http404def get(self, request, id, format=None):obj = self.get_object(id)ser = UserInfoSerializer(obj)data = {'code': 200, "data": ser.data, "message": "OK"}return Response(data, status=status.HTTP_200_OK)def put(self, request, id, format=None):obj = self.get_object(id)ser = UserInfoSerializer(instance=obj, data=request.data)if ser.is_valid():ser.save()data = {'code': 200, "data": ser.data, "message": "OK"}return Response(data, status=status.HTTP_200_OK)else:data = {'code': 400, "message": ser.errors}return Response(data, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, id, format=None):obj = self.get_object(id)obj.delete()return Response(status=status.HTTP_204_NO_CONTENT)

修改路由配置

urlpatterns = [
path('users/', views.UserListView.as_view()),
path('users/<int:id>/', views.UserDetailView.as_view())
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91955.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91955.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信创数据库-DM(达梦)数据库安装教程

官方安装文档在这&#xff1a;安装前准备 | 达梦技术文档 本文也是基于这个来写的&#xff0c;微调了一下。 1&#xff0c;下载安装包 体验版直接到官方下载即可&#xff1a;产品下载 | 达梦在线服务平台 如果是有需要商业版等&#xff0c;需要联系客服申请。 安装包要选择CPU…

docker常用命令集(6)

接前一篇文章&#xff1a;docker常用命令集&#xff08;5&#xff09; 本文内容参考&#xff1a; Docker login/logout 命令 | 菜鸟教程 Docker命令_docker login-CSDN博客 特此致谢&#xff01; 9. docker login 简介 docker login命令用于登录到docker注册表&#xff08…

[LINUX操作系统]shell脚本之循环

1.编写脚本for1.sh,使用for循环创建20账户&#xff0c;账户名前缀由用户从键盘输入&#xff0c;账户初始密码由用户输入&#xff0c;例如:test1、test2、test3......[rootmaster ~]# vim for1.sh #!/bin/bashread -p "请输入账户名称前缀&#xff1a;" prefixread -p…

空间设计:不是餐厅的装饰游戏

餐厅空间设计&#xff0c;是通过布局规划与环境营造&#xff0c;将功能需求、品牌调性与顾客体验融合的系统性工程 —— 它不仅决定顾客「坐得舒不舒服」&#xff0c;更影响「愿不愿意再来」「会不会主动分享」的消费决策。体验感知的第一触点&#xff1a;顾客进门 3 秒内&…

XSS-DOM 2

目录 1 DOMPurify 1.1 漏洞源码 1.2 加载框架 ​编辑 setTimeout 1.3 ok&#xff1f; 1.4 window和document 1.5 Overwrite&#xff08;document.x&#xff09; 1.5.1 打印cookie 1.6 Overwrite2&#xff08;document.x.y&#xff09; 1.6.1 form表单 1.7 toString…

从数据丢失到动画流畅:React状态同步与远程数据加载全解析

在前端开发中&#xff0c;数据状态管理与界面同步始终是核心挑战。近期我在处理一个书签管理应用时&#xff0c;遇到了远程数据加载后无法显示、界面更新异常&#xff0c;甚至动画闪烁等一系列问题。经过多轮调试与优化&#xff0c;最终实现了数据的正确加载与流畅的界面交互。…

MySQL半同步复制机制详解:AFTER_SYNC vs AFTER_COMMIT 的优劣与选择

目录深入分析与利弊对比1. AFTER_COMMIT (不推荐)2. AFTER_SYNC (强烈推荐&#xff0c;MySQL 8.0 默认)总结与强烈建议最佳实践 MySQL 半同步复制主要有两种实现方式&#xff0c;其核心区别在于主库何时回复客户端事务提交成功&#xff08;即何时认为事务完成&#xff09;&…

GEE实战 | 4种非监督分类算法深度解析,附可直接运行的完整代码

在遥感影像处理领域&#xff0c;非监督分类凭借其无需人工标注样本的优势&#xff0c;成为快速了解地物分布的得力助手。它能自动依据像素光谱特征的相似性完成聚类&#xff0c;这种“无师自通”的特性&#xff0c;让地理空间分析变得更加高效。 今天&#xff0c;我们就来深入…

基于落霞归雁思维框架的软件需求管理实践指南

作者&#xff1a;落霞归雁 日期&#xff1a;2025-08-02 摘要 在 VUCA 时代&#xff0c;需求变更成本已占软件总成本的 40% 以上。本文将“落霞归雁”思维框架&#xff08;观察现象 → 找规律 → 应用规律 → 实践验证&#xff09;引入需求工程全生命周期&#xff0c;通过 4 个阶…

企业级AI Agent构建实践:从理论到落地的完整指南

&#x1f680; 引言 随着人工智能技术的快速发展&#xff0c;AI应用正在从简单的工具转变为智能伙伴。企业级AI Agent作为这一变革的核心载体&#xff0c;正在重新定义我们与软件系统的交互方式。本文将深入探讨如何构建一个真正意义上的企业级AI Agent系统。 &#x1f3af; …

电商项目_性能优化_限流-降级-熔断

针对电商系统&#xff0c;在遇到大流量时&#xff0c;必须要考虑如何保障系统的稳定运行&#xff0c;常用的手段&#xff1a;限流&#xff0c;降级&#xff0c;拒绝服务。 一、限流 限流算法&#xff1a;计数器、滑动窗口、漏铜算法、令牌桶算法。 限流的方案 前端限流接入…

javaweb开发之Servlet笔记

第五章 Servlet 一 Servlet简介 1.1 动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源. 例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时…

sqli-labs靶场less26/a

less261.我们打开这一关来看一下&#xff0c;他提示我们空格和其他一些什么都被过滤了2.我们来尝试绕过,按照之前的做法&#xff0c;可以看到闭合方式为单引号&#xff0c;并且过滤了--与#3.我们来尝试绕过一下&#xff0c;发现可以以下的方式绕过&#xff0c;空格用&#xff0…

从Docker衔接到导入黑马商城以及前端登录显示用户或密码错误的相关总结(个人理解,仅供参考)

目录 一、前言 二、从Docker衔接到导入黑马点评 三、谈谈端口映射及我的前端登录显示用户或密码错误 四、总结 一、前言 在学习24黑马SpringCloud课程时&#xff0c;说实话Docker那一块再到导入黑马商城是真的有点折磨&#xff0c;个人感觉老师水平还是很强的&#xff0c;但…

控制建模matlab练习10:滞后补偿器

此练习主要是&#xff1a;关于滞后补偿器。 ①滞后补偿器作用&#xff1b; ②不同滞后补偿器的效果&#xff1b; 一、为什么使用滞后补偿器 滞后补偿器&#xff1a;主要用于改善系统的稳态误差&#xff1b;滞后补偿器设计思路&#xff1a;同时为系统增加一个极点和零点&#xf…

力扣-108.将有序数组转换为二叉搜索树

题目链接 108.将有序数组转换为二叉搜索树 class Solution {public TreeNode Traverse(int[] nums, int begin, int end) {if (end < begin)return null;int mid (begin end) / 2;TreeNode root new TreeNode(nums[mid]);root.left Traverse(nums, begin, mid - 1);ro…

`npm error code CERT_HAS_EXPIRED‘ 问题

问题: npm error code CERT_HAS_EXPIRED npm error errno CERT_HAS_EXPIRED npm error request to https://r2.cnpmjs.org/string_decoder/-/string_decoder-1.3.0.tgz failed, reason: certificate has expired npm error A complete log of this run can be found in: /home…

数据结构---概念、数据与数据之间的关系(逻辑结构、物理结构)、基本功能、数据结构内容、单向链表(概念、对象、应用)

数据结构在数据结构部分&#xff0c;研究数据在内存中如何存储。数据存储的形式有两种&#xff1a;变量和数组&#xff08;数据结构的顺序表&#xff09;。一、什么是数据结构&#xff1f;数据类型被用来组织和存储数据。程序设计 数据结构 算法二、数据与数据之间的关系1、逻…

CMS框架漏洞

一、WordPress姿势一1.下载vulhub靶场cd /vulhub/wordpress/pwnscriptum docker-compose up -d2.我们进入后台&#xff0c;网址拼接/wp-admin/3.我们进入WP的模板写入一句话木马后门并访问其文件即可GetShell4然后我们拼接以下路径/wp-content/themes/twentyfifteen/404.php&am…

控制建模matlab练习07:比例积分控制-③PI控制器的应用

此练习主要是比例积分控制&#xff0c;包括三部分&#xff1a; ①系统建模&#xff1b; ②PI控制器&#xff1b; ③PI控制器的应用&#xff1b; 以下是&#xff0c;第③部分&#xff1a;PI控制器的应用。 一、比例积分控制的应用模型 1、整个系统是如图&#xff0c;这样一个单位…