一 安装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