Django REST framework是一个基于django框架开发的组件,本质是一个django的app。
不基于drf也可以实现restful规范来开发接口程序,但是使用它可以帮程序员快速开发出一个遵循restful规范的程序。
安装
pip3 install djangorestframework
简单使用
-
settings中注册app
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework' ]
-
路由, 一个路由可以对应多个操作
from django.conf.urls import url from django.contrib import admin from api import views urlpatterns = [ url(r'^drf/info/', views.DrfInfoView.as_view()), ]
-
视图CBV,继承APIView类
from rest_framework.views import APIView from rest_framework.response import Response class DrfInfoView(APIView): def get(self,request,*args,**kwargs): data = [ {'id': 1, 'title': '震惊了...', 'content': '...'}, return Response(data)
这样我们就实现了一个简单的drf应用。
DRF的应用场景
前后端分离项目、参与为app写接口时,用drf会比较方便。
drf 解析器
解析器,根据用户请求体格式不同进行数据解析,解析之后放在request.data
中。
在进行解析时候,drf会读取http请求头 content-type:
- 如果content-type:x-www-urlencoded,那么drf会根据 & 符号分割的形式去处理请求体。 user=wang&age=19
- 如果content-type:application/json,那么drf会根据 json 形式去处理请求体。 {"user":"wang","age":19}
drf 序列化
对对象或对象列表(queryset)进行序列化操作以及表单验证的功能。
drf的 serializers模块提供两个功能:
- 数据校验
- 序列化
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^info/$', views.InfoView.as_view()),
url(r'^drf/info/$', views.DrfInfoView.as_view()),
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),
url(r'^new/category/$', views.NewCategoryViewpython.as_view()),
url(r'^new/category/(?P<pk>\d+)/$', views.NewCategoryView.as_view()),
]
from rest_framework import serializers
class NewCategorySerializer(serializers.ModelSerializer):
"""定义一个类,进行序列化"""
class Meta:
model = models.Category
# fields = "__all__"
fields = ['id','name']
class NewCategoryView(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all()
ser = NewCategorySerializer(instance=queryset,many=True) # 进行数据校验,many=True表示多个对象数据
return Response(ser.data) # 返回数据
else:
model_object = models.Category.objects.filter(id=pk).first()
ser = NewCategorySerializer(instance=model_object, many=False) # many=True表示一个对象数据
return Response(ser.data)
def post(self,request,*args,**kwargs):
ser = NewCategorySerializer(data=request.data) # post请求,对提交的数据进行序列化校验
if ser.is_valid():
ser.save() # 可以直接保存到数据库中
return Response(ser.data)
return Response(ser.errors)
def put(self,request,*args,**kwargs):
pk = kwargs.get('pk')
category_object = models.Category.objects.filter(id=pk).first()
ser = NewCategorySerializer(instance=category_object,data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
def delete(self,request,*args,**kwargs):
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).delete()
return Response('删除成功')
序列化时,外键关联字段、choices选择如何在前端显示中文:
source: 找源头,会判断是否可执行,可执行自动加 (),不用自己加 ()例如choices:source='get_status_display'
depth = 1, 将外键关联的表都显示出 0--10
-
钩子:x1 = serializers.SerializerMethodField()
def get_x1(self, obj):
return obj.xxx
obj是当前对象。
-
ManyToMany显示:
tag_title = serializers.SerializerMethodField() def get_tag_title(self, obj): tag_obj = obj.tag.all().values('id', 'title') return tag_obj
-
如果GET显示和POST提交的字段不相同,可以再定义一个
class FromSerializer(serializers.ModelSerializer): class Meta: model = models.Article fields = '__all__'
示例:
class NewSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name', required=False) # required=False 表示可以不用提交数据 status_choice = serializers.CharField(source='get_status_display', required=False) # x1 = serializers.SerializerMethodField() # x2 = serializers.SerializerMethodField() tag_title = serializers.SerializerMethodField() class Meta: model = models.Article fields = ['title', 'summary', 'content', 'category', 'category_name', 'status', 'status_choice', 'tag', 'tag_title'] # depth = 1 # def get_x1(self, obj): # return obj.category.name # # def get_x2(self, obj): # return obj.get_status_display() def get_tag_title(self, obj): tag_obj = obj.tag.all().values('id', 'title') return tag_obj