REST-framework快速构建API--初体验
作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/10392593.html
目录
一、快速上手
二、结果序列化
三、基于REST-framework序列化
四、使用ModelSerializer
五、单条数据操作
六、超链接API
一、快速上手
1、环境准备
安装restframework,注册app
1 | pip install djangorestframework |
1 2 3 4 5 6 7 8 9 10 | INSTALLED_APPS = [ 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'app01.apps.App01Config' , 'rest_framework' , ] |
2、url
1 2 3 4 | urlpatterns = [ url(r '^admin/' , admin.site.urls), url(r '^publish/' , views.PublishView.as_view()), ] |
3、models
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. 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 |
4、views
基于CBV方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render,HttpResponse # Create your views here. from .models import Publish from rest_framework.views import APIView class PublishView(APIView): def get (self,request): #序列化方式4rest_framework from rest_framework.response import Response publish_list = Publish.objects.all() ps = PublishSerializers(publish_list, many=True) return Response(ps.data) def post(self,request): return HttpResponse( 'POST' ) |
5、测试
二、结果序列化
API返回结果的形式,json是非常流行的。但是我们在序列化结果时,有多种方式,每种方式实现的方式不同。
1、原生json方式
1 2 3 | import json publish_list = list(Publish.objects.all().values()) return HttpResponse(json.dumps(publish_list)) |
使用json方式对结果进行强转,先把结果强转成列表的方式,然后通过json的dumps方式对结果进行格式化。
注意:
这种方式实现最简单,也可以自定制需要返回的字段,通过在values中填写自己需要的字段即可。
2、model_to_dict方法
1 2 3 4 5 6 7 | #序列化方式2 # from django.forms.models import model_to_dict # publish_list = Publish.objects.all() # data = [] # for obj in publish_list: # data.append(model_to_dict(obj)) # return HttpResponse(data) |
通过models自带的model_to_dict方法直接把obj对象转换成字典的形式,然后返回。缺点:需要把每个对象再次进行处理。
3、django自带的serializers方法
1 2 3 4 5 | #序列化方式3 # from django.core import serializers # publish_list = Publish.objects.all() # data = serializers.serialize("json", publish_list) # return HttpResponse(data) |
三、基于REST-framework序列化
1 2 3 4 5 6 7 8 9 10 11 12 | from rest_framework import serializers class PublishSerializers(serializers.Serializer): name=serializers.CharField(max_length=32) email=serializers.CharField() from rest_framework.views import APIView视图函数继承APIView方法 #序列化方式4rest_framework from rest_framework.response import Response publish_list = Publish.objects.all() ps = PublishSerializers(publish_list, many=True) return Response(ps.data) |
既然有了前面三种方法,为什么这里还要用restframework的第四种方法呢?原因如下:
a、对于表结构复杂的情况,前面三种没有涉及到,需要我们自己去通过写逻辑代码实现;
b、对于我们需要的返回表结构中字段的结果,定制也是个问题,比如,我们的api只需要返回指定的几个字段;
c、对于我们后面对资源的操作,比如POST动作,需要对结果进行保存,是不是我们每次都需要自己写create方法去保存结果呢?
d、对于错误的处理;
等等.....诸如此类的需要考虑的问题,rest-framework都帮我们写好了逻辑,只需要我们去调用即可。
对于复杂表结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from rest_framework import serializers class BookSerializers(serializers.Serializer): title=serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() #一对多,可以通过source指定列名,默认为str或unicode方法显示的 publish=serializers.CharField(source= "publish.name" ) #对于多对多我们可以自定义get_field方法,将object添加进去 authors=serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp |
1 2 3 4 5 6 7 | class BookViewSet(APIView): def get (self,request,*args,**kwargs): book_list=Book.objects.all() bs=BookSerializers(book_list,many=True) return Response(bs.data) |
注意:这里的many=True,表示对queryset进行操作,默认为对model对象进行操作。
四、使用ModelSerializer
1 2 3 4 5 | class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields= "__all__" depth=1 |
保存数据:
1 2 3 4 5 6 7 8 9 | def post(self,request,*args,**kwargs): bs=BookSerializers(data=request.data,many=False) if bs.is_valid(): # print(bs.validated_data) bs.save() return Response(bs.data) else : return HttpResponse(bs.errors) |
通过ModelSerializer方法,类似ModelForm方法,我们可以通过Meta类直接指定Model、fields,就能满足我们的需求。操作哪个表,提交哪些字段。save方法其实后端是调用的create方法,将我们提交的数据进行保存。
注意:
在BookSerializers里面,我们同样可以自定义返回多对多或一对多字段内容;
1 2 3 4 5 6 7 8 9 10 11 12 | class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields= "__all__" depth=1 publish=serializers.CharField(source= "publish.name" ) authors=serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp |
但是这里如果使用ModelSerializer方法,使用save方法时,ModelSerializer默认自带的create方法不支持多对多的保存,需要我们重载create方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields= "__all__" # exclude = ['authors',] # depth=1 def create(self, validated_data): authors = validated_data.pop( 'authors' ) obj = Book.objects.create(**validated_data) obj.authors.add(*authors) return obj |
五、单条数据操作
针对单条数据进行操作,比如books/1(GET/PUT/DELETE)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class BookDetailViewSet(APIView): def get (self,request,pk): book_obj=Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj) return Response(bs.data) def put(self,request,pk): book_obj=c bs=BookSerializers(book_obj,data=request.data) if bs.is_valid(): bs.save() return Response(bs.data) else : return HttpResponse(bs.errors) def delete(self,request,pk): Book.objects.filter(pk=pk).delete() return Response() |
注意:
put进行更新数据时,需要把单条数据的每个字段写全,即使之前已经是完整的一条记录,否则会报错。
六、超链接API
1 2 3 4 5 6 7 8 9 | class BookSerializers(serializers.ModelSerializer): publish= serializers.HyperlinkedIdentityField( view_name= 'publish_detail' , lookup_field= "publish_id" , lookup_url_kwarg= "pk" ) class Meta: model=Book fields= "__all__" #depth=1 |
urls
1 2 3 4 5 6 | 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" ), ] |
注意:
1、反向解析,通过name进行命名,这个代表前面的URL,不管pk怎么变化都可以引用;
2、view_name为反向解析的name,lookup_field为对应的哪个字段,这里的pk对应的是Model里面的id字段;
3、lookup_url_kwarg是命名url里面的分组关键字;
4、需要在views函数里面新增一个context={'request':request}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class BookView(APIView): def get (self,request): book_list=Book.objects.all() bs=BookModelSerializers(book_list,many=True,context={ 'request' : request}) return Response(bs.data) def post(self,request): # post请求的数据 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save()# create方法 return Response(bs.data) else : return Response(bs.errors) |
注意:这里有一个问题,使用超链接post数据的时候,会有一个报错:
需要去掉超链接的配置才能POST数据,这里还没找到解决办法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」