django☞restful简单使用

阅读量: zyh 2020-03-07 13:33:44
Categories: > Tags:

前言

官方快速教程:Quickstart - Django REST framework (django-rest-framework.org)

安装

pip install djangorestframework

配置

settings.INSTALLED_APPS加入'rest_framework.authtoken','rest_framework'

其中rest_framework.authtoken是简单的 Token 认证

settings.py 中加入以下代码:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication'  # 开启 Token 认证
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated', # 全局接口权限:开启全局认证
    ],
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 接口分页
    # 'PAGE_SIZE': 10
}

具体

image-20210805152047616

大概的界面就如上图所示:

  1. 右上角是一个登录UI
  2. 正面是请求地址/方法之类的,以及返回的数据

关于右上角的登录UI

# 项目根APP里的 urls.py
from django.urls import path, include
urlpatterns += [
    path('api-auth/', include('rest_framework.urls')), 
]

大致的一个流程

Request☞DjangoUrLs☞AppRootUrL☞APIUrL☞APIView☞API序列化☞DjangoModel

假设你的API地址是 /api-user/user

DjangoUrLs路由

项目根路由

urlpatterns += [
    path('api-user/', include(loginurls, namespace="login")),
]

AppRoutUrL

loginurls文件:App根路由

app_name="login"
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse

@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'users': reverse('login:user-list', request=request, format=format),
        'snippets': reverse('login:asset-list', request=request, format=format)
    })


# API根路由
urlpatterns += [
    path('', api_root),
]

APIURL

user_list = views.UserViewSet.as_view({
    'get': 'list'
})
user_detail = views.UserViewSet.as_view({
    'get': 'retrieve'
})
urlpatterns += [
    path('user/', user_list, name='user-list'),
    path('user/<int:pk>/', user_detail, name='user-detail')
]

APIViews

from login import models as loginmodels
from login.serializers import UserSerializer
from django.contrib.auth.models import User

from rest_framework import permissions
from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list` and `retrieve` actions.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAdminUser]

API序列化

from rest_framework import serializers
from login import models as loginmodels
from django.contrib.auth.models import User

class UserSerializer(serializers.HyperlinkedModelSerializer):
    # 显示的定义两个数据字段的查找方法,一个是user的关联外键 user_asset,一个是 HyperlinkedModelSerializer 所需的链接字段 url
    user_asset = serializers.HyperlinkedRelatedField(     # user_asset 是 User主表的外键名(related_name)
        view_name="login:asset-detail", read_only=True
    )

    url = serializers.HyperlinkedIdentityField(
        view_name='login:user-detail',   # 默认 HyperlinkedModelSerializer 的 url 字段查找的视图名是 {model_name}-detail。 这里显示指定视图
    )

    class Meta:
        model = User
        fields = ['url', 'id', 'username', 'user_asset']  # api返回的数据

简单的Token认证

通过API拿到数据,一般我们会开启认证,例如Token方式

"""
Token URL
"""
from login import views as loginviews
urlpatterns += [
    path('api/gettoken/', loginviews.CustomAuthToken.as_view()), # 通过发起POST获取token,{"username": "xxx", "password":xxx}
]
"""
views
"""
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response

class CustomAuthToken(ObtainAuthToken):
    #throttle_classes = 
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                        context={'request': request})
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user_id': user.pk,
            'email': user.email
        })