1.1目标
1.配置Restful API
2.Swagger UI展示Restful API
3.在Swagger UI页面测试API
4.测试JWT认证的API
2.环境版本
以下包建议在虚拟环境下安装
Django 3.2.12
Djangorestframework 3.13.1
Django-rest-swagger 2.2.0
Djangorestframework-jwt 1.11.0
操作系统:Win10
3.Django settings.py配置
LOGIN_URL = ‘/login/’ 配置默认的登录url
LOGOUT_URL = ‘/logout/’ 配置默认的登出url
这两项都会体现在 Swagger UI页面的Session Login和Logout按钮中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'baby_app.apps.BabyAppConfig',
'rest_framework',
'rest_framework_swagger',
'django_filters',
]
# rest framework配置
REST_FRAMEWORK = { # restful插件配置项
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticatedOrReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # username和password形式认证
'rest_framework.authentication.SessionAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 全局jwt
),
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 3
}
LOGIN_URL = '/login/'
LOGOUT_URL = '/logout/'
4.1Django models.py配置
我的应用是baby_app
路径:D:\VirtualEnv\django_env\django_new_project\baby_app\models.py
元类的db_table 可以自定义表名
from django.contrib.auth.hashers import make_password
from django.db import models as db
class Money(db.Model):
id = db.AutoField(primary_key=True)
card_id = db.IntegerField(null=False)
user = db.CharField(max_length=5, null=True)
bank = db.CharField(max_length=128, null=True)
password = db.CharField(max_length=128, null=True)
def set_password(self, password): # 用来设置密码的方法,接受密码作为参数
self.password = make_password(password) # 将生成的密码保持到对应字段
class Meta:
db_table = 'money'
4.2Django serializers.py配置
1.我的应用是baby_app,所以我在baby_app下创建D:\VirtualEnv\django_env\django_new_project\baby_app\serializers.py
2.继承于HyperlinkedModelSerializer的子类在序列化结果中会自动生成URL字段,如下图
3.序列化类的作用是把从数据库中读取到的字段信息转化为可在网络中传输和在硬盘可存储的形式,也可以将从网络中传输的和硬盘中存储的数据读取并保存至数据库中
4.__all__是展示所有字段
from rest_framework import serializers
from .models import Money
class MoneySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Money
fields = '__all__'
4.3Django views.py配置
1.我的应用是baby_app,所以我在baby_app下创建D:\VirtualEnv\django_env\django_new_project\baby_app\views.py,如下图所示
2.ModelViewSet视图集继承了
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet
提供多个对象列表视图,查看,创建,更新,删除单个对象视图,对应着序列化类里展示的字段
3.fileter_backends 用于配置要使用的过滤插件,filter_fields 配置过滤字段
4. 因为Money数据模型有密码字段,想用Django的加密方式加密,所以重写了mixins.CreateModelMixin的create方法和mixins.UpdateModelMixin的update方法
5.schema_view = get_swagger_view(title=‘任务’)可以自动搜索到自定义的视图集MoneyViewSet
6.此视图集类的说明“API View that receive POST and GET request with some param”会显示在API文档里,根据代码实时更新
from rest_framework import viewsets,status
from rest_framework.response import Response
from .serializers import MoneySerializer
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication
from django_filters.rest_framework import DjangoFilterBackend
from django.contrib.auth.hashers import make_password
from .models import Money
class MoneyViewSet(viewsets.ModelViewSet):
"""
API View that receive POST and GET request with some param
"""
queryset = Money.objects.all()
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
serializer_class = MoneySerializer
fileter_backends = (DjangoFilterBackend,)
filter_fields = ('card_id', 'user')
def create(self, request, *args, **kwargs):
data = request.data.copy()
data['password'] = make_password(request.data['password'])
# print(request.data)
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def update(self, request, *args, **kwargs):
data = request.data.copy()
data['password'] = make_password(request.data['password'])
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
schema_view = get_swagger_view(title='任务')
5.将视图集注册到router
1.我的应用是baby_app,所以我在baby_app下创建D:\VirtualEnv\django_env\django_new_project\baby_app\routers.py
from rest_framework import routers
from .views import MoneyViewSet
router.register(r'moneys', MoneyViewSet)
6.编写项目的urls.py
1.我的项目是django_new_project,路径:D:\VirtualEnv\django_env\django_new_project\django_new_project\urls.py
2.obtain_jwt_token是rest_framework_jwt自带的视图,可以在Swagger UI页面看到
3.schema_view是自动搜索到的视图集
from django.urls import path, include,re_path
from baby_app.routers import router
from baby_app.views import schema_view
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('api/', include(router.urls)), #固定写法
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # 固定写法
path(r'authorizations/', obtain_jwt_token, name='authorizations'),
re_path(r'^docs',schema_view)
]
7.启动Django项目
以下是我的Django项目的Pycharm里的配置
以下是启动成功的图
8.1展示Restful API
浏览器输入http://127.0.0.1:8000/docs
此页面未登录,目前只能测试API的GET请求
点击Session Login按钮会直接跳转到项目应用的登录页面(前提是在应用中已经配置了登录和登出的路由,可参考我后期的博文)
登录后可以显示全部的API操作
8.2测试Restful API GET请求
8.3测试JWT认证的API
因为此API做了JWT认证,POST,PUT,PATCH,DELETE请求需要先获取token,然后塞到请求头中才能正常请求API,而Swagger UI不适合做这项事情,故我用Postman演示。
1.首先获取token
2.将token塞到POST请求的请求头中,注意JWT和token值中间是有空格的,千万注意。
8.4测试JWT认证的API DElETE请求
请求url不能少最后面的斜杠