官方快速入门教程有坑,一直找不到关于django rest framework好的书籍和好的博文,本文都是基于网上收集整理的资料
Django REST framework(以下简称 DRF)是一个开源的 Django 扩展,提供了便捷的 REST API 开发框架,是实现前后端分离的典型案例。所谓前后端分类,即前端负责页面展示和与用户的交互,后端则负责API接口
RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
那什么是RESTful架构呢?
(1)**每一个URI代表一种资源;**简单理解就是url指向网络上的一个信息如文本,图片,音频等,要获取这个资源只需访问这个url即可
(2)**客户端和服务器之间,传递这种资源的某种表现层;**所谓表现层即指把“资源”呈现出来的的形式,如文本(资源)可以用txt格式,html格式,json格式(表现层)来呈现。访问一个网站,客户端和服务端会传递这种表现层,以实现下一个步骤:状态转化
(3)**客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。**因为http协议是无状态协议,所有状态都保存在服务端,客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
参考文章:http://www.ruanyifeng.com/blog/2011/09/restful.html
序列化器用于处理前端发来的json数据,因为前端发送给后端的是json数据,但是后端要向数据库存储数据,json数据是不被允许的.反序列化则反过来理解。
简单来说就是通过映射,把数据结构转换符合前端/后端的数据,就是充当一个翻译官的作用
(1)序列化
模板:
from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())
从djang.core导入它,然后调用它的serialize方法。
这个方法至少接收两个参数,第一个是你要序列化成为的数据格式,这里是‘xml’,第二个是要序列化的数据对象
class YourSerializer(Serializer):
field1 = Field()
def save(self, validated_data):
# save your data here
return saved_data
def update(self, instance, validated_data):
# update your instance
return instance
序列化之后的数据保存在 serializer.data
中的,可以使用 SomeRenderer().render(serializer.data)
将其序列化为字符串对象作为 Response body 返回。
(2)反序列化
模板:
data = SomeParser().parse(incoming_stream)
serializer = YourSerializer(data=data)
if serializer.is_valid(): # 这里会根据 Serialzier 的 Field 和自定义验证工具进行数据校验
logging.info(serializer. validated_data)
serializer.update() # 或者 serializer.create()
对于自定义 Serializer,你需要自己实现 create
和 update
方法。
你也可以使用 serializer.save(**data)
,save
方法的行为取决于初始化的方式
# .save() 会创建一个新实例
serializer = CommentSerializer(data=data)
# .save() 会更新 `comment` 实例
serializer = CommentSerializer(comment, data=data)
反序列化时应该先运行 serializer.is_valid()
判断数据是否合法,serializer.is_valid(raise_exception=True)
会直接返回 400 信息。
DRF 通过 View 提供 API 接口,一个 View 可以对应多个 Renderer,针对不同的渲染条件提供不同的输出格式(HTML/XML/JSON)
ViewSet 则是 View 的一个封装,一个 ViewSet 可以为同一个 URL 根据请求方法提供不同的接口。尤其是 ModelViewSet 会自动根据 Model 的定义生成 REST 接口和 URL,能够快速生成网站的一整套 API。
定义一个 ViewSet 需要为其声明 queryset
和 serializer
属性
模板:
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
Meta 继承:
class AccountSerializer(MyBaseSerializer):
class Meta(MyBaseSerializer.Meta):
model = Account
DRF使用Requests对象扩展了原生的HttpRequest,并提供了更灵活的请求处理。Requests对象的核心属性就是request.data,可以处理任意数据,接受POST、PUT和PATCH方法。
DRF的使用主要分为三步:定义资源 - 实现HTTP方法 - 配置URL
确保自己的虚拟环境安装好了djangorestframework
pip install djangorestframework
在项目的setting中编写
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'demo',
'rest_framework', #添加djangorestframework框架
]
(1)定义模型资源
在app中的models.py,定义模型
from django.db import models
class Fruit(models.Model):
name = models.CharField(u'名称', default="", max_length=255)
price = models.FloatField(u"单价", default=0)
(2)实现序列化
from rest_framework import serializers #在框架中导入
from .models import Fruit
class FruitSerializer(serializers.HyperlinkedModelSerializer):
class Meta: #模型的元数据
model = Fruit #选中模型
fields = ('name', 'price') #选择转换的字段
HyperlinkedModelSerializer
类类似于ModelSerializer
类,不同之处在于它使用超链接来表示关联关系而不是主键。(3)ModelSerializer,HyperlinkedModelSerializer与Serializer
`
ModelSerializer类能够让你自动创建一个具有模型中相应字段的
Serializer`类。
这个ModelSerializer
类和常规的Serializer
类一样,不同的是:
.create()
方法和.update()
方法。HyperlinkedModelSerializer
基本与ModelSerializer
一样,不同之处:
在views.py中编写,用提供默认行为的现有基类
from rest_framework.viewsets import ModelViewSet #引入默认视图集
from .models import Fruit
from .serializers import FruitSerializer #引入序列化文件
"""
用于查看和编辑用户实例的视图集。
"""
class FruitViewSet(ModelViewSet):
queryset = Fruit.objects.all()
serializer_class = FruitSerializer
FruitViewSet直接继承ModelViewSet,ModelViewSet继承了一系列Mixins类的HTTP方法。如果需要自定义HTTP方法,可以继承APIView类,或者Mixins类,还可以完全自定义
from django.urls import include, path
from rest_framework import routers #引入自动URL路由模板
from demo.views import FruitViewSet
router = routers.DefaultRouter() #API 向导
router.register(r'fruit', FruitViewSet) #指定路由,处理请求的类
urlpatterns = [
path('api/v1/', include(router.urls)), #确定url
]
prefix
- 用于此组路由的URL前缀 (2)viewset
- 处理请求的viewset类list
, create
, retrieve
, update
, partial_update
和 destroy
动作的路由,还包括一个默认返回所有列表视图的超链接的API根视图至此一个简单的API便实现了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bifaeNJo-1592288934675)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20200413103713150.png)]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
默认权限策略可以使用DEFAULT_PERMISSION_CLASSES
设置进行全局设置
class YourView(BaseView):
paginate_by = 10 # 覆盖 settings 中的默认分页
max_paginate_by = 100 # 限制最大分页大小
也可以动态地去判断最大分页大小:
class YouView(BaseView):
...
def paginate_queryset(self, queryset):
self.paginator.max_page_size = YOUR_PAGE_SIZE_LIMIT
return super(YouView, self).paginate_queryset(queryset)
from rest_framework import serializers
#对应主键
class HospitalSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Hospital
fields = '__all__'
#对应外键
class HospitalPicSerializer(serializers.HyperlinkedModelSerializer):
hospital = HospitalSerializer()
class Meta:
model = HospitalPic
fields = '__all__'
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
限制API查询的频率,可以根据用户不同,精确到每天、每小时、每分钟
Django-rest-framework为我们提供了许多现成的mixins,可以用于快速组合接口
from .models import Fruit
from .serializers import FruitSerializer
from rest_framework import mixins
from rest_framework import generics
class FruitList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Fruit.objects.all()
serializer_class = FruitSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
from rest_framework import generics
class FruitList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Fruit.objects.all()
serializer_class = FruitSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)