django-rest-framework 框架

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dqchouyang/article/details/80293354

一 安装rest-framework

pip install djangorestframework==3.5.4

注:安装时,尽量指定版本号,避免包更新出现不兼容问题

二 settings参数设置

把框架加入到应用里
INSTALLED_APPS = (  
    ...
    'rest_framework',
)

REST_FRAMEWORK = {  
    # API json渲染
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    # 解析器
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ),
    # 认证
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    ),
    # 权限
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    ),

    # 分页器
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',

    # 每页记录数
    'PAGE_SIZE': 20,

    # 查询页面过滤
    'SEARCH_PARAM': 'search',

    # 排序参数
    'ORDERING_PARAM': 'ordering',
    ......
}

三 URL配置

urls.py文件中应有内容如下:

from rest_framework import routers  
router = routers.SimpleRouter()  
router.register(r'users', UserViewSet)  
urlpatterns = router.urls  

注:按照以上写法,我们的URL末尾是以一个斜杠结尾的。

api/users/

如果末尾不要以斜杠结尾,修改内容如下:

router = routers.SimpleRouter(trailing_slash=False)

四 URL标准

URL格式 HTTP请求方式 操作 功能
{prefix}/ GET list 查询列表
{prefix}/ POST create 提交数据
{prefix}/{pk}/ Get retrieve 查询某条详情
{prefix}/{pk}/ PUT update 更新某条数据所有字段
{prefix}/{pk}/ PATCH partial_update 更新某条数据部分字段
{prefix}/{pk}/ DELETE destroy 删除某条数据

当然 在开发的过程中,如果只是使用框架的这些标准接口,那局限性就太大了,所以,框架已经替你考虑了,接口url可自定义。

from myapp.permissions import IsAdminOrIsSelf  
from rest_framework.decorators import detail_route, list_route  
class UserViewSet(ModelViewSet):  
    ...

    @detail_route(methods=['get'], permission_classes=[IsAdminOrIsSelf])
    def get_info(self, request, pk=None):
        ...
    # ^users/{pk}/get_info/$ ,GET请求方式    

    @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')
    def set_password(self, request, pk=None):
        ...
    # ^users/{pk}/change-password/$ ,POST请求方式 

    @list_route(methods=['get'], permission_classes=[IsAdminOrIsSelf])
    def get_phone(self, request):
        ...
    # ^users/get_phone/$ ,GET请求方式    

    @list_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-name')
    def set_name(self, request):
        ...
    # ^users/change-name/$ ,POST请求方式 

五 URL规范

优秀的URL是可以表达这个接口所实现的功能的:

api/zoos/   #所有动物园  
api/zoos/1/   #id为1的动物园  
api/zoos/1/animals/   #id为1的动物园中的所有动物  

来做两道多选题:

修改某动物园里的动物的数量。
A. api/zoos/count/
B. api/zoos/{id}/amount/
C. api/zoos/{id}/animals/count/
D. api/zoos/{id}/animals/amount/
E. All above

查询某动物园的哪些动物体重超过30kg?
A. api/zoos/animals/weight/30/
B. api/zoos/{id}/animals/weight/30/
C. api/animals/?zoos={id}&weight=30
D. api/zoos/areas/animals/?weight=30
E. All above

规范:

区分实例
大体理解它要实现的功能
URL配置灵活(30)
避免层级过深的

六 序列化

什么是序列化? 你这个问题,在大街上问100个人,有99个都不知道。

1 原理

实例对象 => 原生数据类型 => JSON(XML)

User => b’{“name”: 1}’ => {“name”: 1}

2 序列化(输出)与反序列化(输入)

# user 为实例对象
serializer = UserSerializer(user)  
serializer.data  
# {"name": 1}

# data 为{"name": 1}
serializer = UserSerializer(data=data)  
serializer.is_valid()  
# True
serializer.save()  

3 serializer跟form是很像的,所以form的一些用法,在serializer中都能找到熟悉的感觉。可参考着学习。

form.is_valid()  
serializer.is_valid()  
form.is_valid(raise_exception=True)  
serializer.is_valid(raise_exception=True)  
form.save()  
serializer.save()  
form.save(user=request.user)  
serializer.save(user=request.user)  
form.errors  
serializer.errors 

4 序列化一个对象

serializer = UserSerializer(user)

序列化一个集合

serializer = UserSerializer(queryset, many=True)

当然,在实际的使用中,有时我们所要的序列化结果是要随请求中带有的参数来决定的,这个时候,你就需要将request传给序列化类,然后再做具体处理

serializer = UserSerializer(queryset, many=True, context={'request': request})

5 ModelSerializer一个完整集成的序列化类,我要实现一个模型的序列化,只需要继承它,并配置一下model和fields,就可以简单实现。

class AccountSerializer(serializers.ModelSerializer):  
    class Meta:
        model = Account
        fields = ('id', 'account_name', 'users', 'created')

它还有很多一些很炫的用法如下:

# 模型的所有字段都要序列化,all 来搞定
class AccountSerializer(serializers.ModelSerializer):  
    class Meta:
        model = Account
        fields = '__all__'

# 模型中不要序列化某个字段,exclude(fields活exclude要有一个)
class AccountSerializer(serializers.ModelSerializer):  
    class Meta:
        model = Account
        exclude = ('age',)

# 自定义模型中没有的字段,并且这样的字段有好多属性是可设置的,如是否只读,只写,调用方法取值等
class AccountSerializer(serializers.ModelSerializer):  
    url = serializers.CharField(source='get_absolute_url', read_only=True)

    class Meta:
        model = Account
        fields = "__all__"

# 定义哪些字段为只读
class AccountSerializer(serializers.ModelSerializer):  
    class Meta:
        model = Account
        fields = ('id', 'account_name', 'users', 'created', 'status')
        read_only_fields = ('status',)

七 view

view层主要是一个请求进来,程序处理,然后返回的过程。view可以继承的类有:APIView, Generic, Mixins, ViewSets, GenericViewSet, ModelViewSet等,其实这部分的内容跟 四 URL标准 有交集。我举1个例子,说下,其他的大家就去看源码吧,都是一样的道理。

# ModelViewSet 开发中最常用的类
class AccountViewSet(viewsets.ModelViewSet):  
    queryset = Account.objects.all()
    serializer_class = AccountSerializer
    permission_classes = [IsAccountAdminOrReadOnly]

这样只继承 ModelViewSet 类的API,其实它已经完成了对模型的增删改查功能,使编码更简单,更简洁。可能有的时候,某些模型是不需要提供其中某类功能的API的,那么这时候,你就不能继承 ModelViewSet 了,你可能需要继承 Generic 或 Mixins 中的子类或者它们的一些混合继承,酌情处理。

八 request 和 response

REST 的 Request 类扩展了标准的 HttpRequest类。所以在请求提交数据的时候,标准的http请求可以通过 request.POST 和 request.FILES 来获取提交的内容,但经过扩展的REST可以通过 request.data 来搞定这一切。

当一个http的 get 请求发来的时候,标准写法是用 request.GET 来获取url中问号后传参的值,而REST是用 request.query_params 来获取,尽管request.GET 依然管用。

关于 response 需要留意一下几个参数

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

根据具体API的需求,一般重要的是data和status,data就是API需要返回的数据,status的值可以根据API处理的不同结果,参考 九 status code 中给出的值,当然,要以实际为准,标准为辅,有标准大家才能看的懂,大家也都尽量遵循标准。

九 status code

http状态码,大体熟悉就可以了

# 1XX 一种临时的状态,很少见
HTTP_100_CONTINUE  
HTTP_101_SWITCHING_PROTOCOLS

# 2XX 一般是请求成功了
HTTP_200_OK  
HTTP_201_CREATED  
HTTP_202_ACCEPTED  
HTTP_203_NON_AUTHORITATIVE_INFORMATION  
HTTP_204_NO_CONTENT  
HTTP_205_RESET_CONTENT  
HTTP_206_PARTIAL_CONTENT  
HTTP_207_MULTI_STATUS

# 3XX 一般是代理、跳转
HTTP_300_MULTIPLE_CHOICES  
HTTP_301_MOVED_PERMANENTLY  
HTTP_302_FOUND  
HTTP_303_SEE_OTHER  
HTTP_304_NOT_MODIFIED  
HTTP_305_USE_PROXY  
HTTP_306_RESERVED  
HTTP_307_TEMPORARY_REDIRECT

# 4XX 一般是客户端请求有问题
HTTP_400_BAD_REQUEST  
HTTP_401_UNAUTHORIZED  
HTTP_402_PAYMENT_REQUIRED  
HTTP_403_FORBIDDEN  
HTTP_404_NOT_FOUND  
HTTP_405_METHOD_NOT_ALLOWED  
HTTP_406_NOT_ACCEPTABLE  
HTTP_407_PROXY_AUTHENTICATION_REQUIRED  
HTTP_408_REQUEST_TIMEOUT  
HTTP_409_CONFLICT  
HTTP_410_GONE  
HTTP_411_LENGTH_REQUIRED  
HTTP_412_PRECONDITION_FAILED  
HTTP_413_REQUEST_ENTITY_TOO_LARGE  
HTTP_414_REQUEST_URI_TOO_LONG  
HTTP_415_UNSUPPORTED_MEDIA_TYPE  
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE  
HTTP_417_EXPECTATION_FAILED  
HTTP_422_UNPROCESSABLE_ENTITY  
HTTP_423_LOCKED  
HTTP_424_FAILED_DEPENDENCY  
HTTP_428_PRECONDITION_REQUIRED  
HTTP_429_TOO_MANY_REQUESTS  
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE  
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS

# 5XX 一般为服务器程序报错或网络问题
HTTP_500_INTERNAL_SERVER_ERROR  
HTTP_501_NOT_IMPLEMENTED  
HTTP_502_BAD_GATEWAY  
HTTP_503_SERVICE_UNAVAILABLE  
HTTP_504_GATEWAY_TIMEOUT  
HTTP_505_HTTP_VERSION_NOT_SUPPORTED  
HTTP_507_INSUFFICIENT_STORAGE  
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED 

这里写图片描述

猜你喜欢

转载自blog.csdn.net/dqchouyang/article/details/80293354