04: DjangoRestFramework使用
Django其他篇
目录:
- 1.1 DjangoRestFramework基本使用
- 1.2 drf认证&权限 模块
- 1.3 djangorestframework 序列化
- 1.4 djangorestframework 分页
1.1 DjangoRestFramework基本使用 返回顶部
1、回顾CBV基本使用
from django.contrib import admin
from django.urls import path,re_path,include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
]
urls.py
from django.contrib import admin
from django.urls import path,re_path,include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
]
users/urls.py
import json
from django.shortcuts import render,HttpResponse
from django.views import View
class HomeView(View):
def dispatch(self, request, *args, **kwargs):
return super(HomeView, self).dispatch(request, *args, **kwargs)
def get(self, request):
return HttpResponse('get')
def post(self, request):
return HttpResponse('post')
users/views.py
2、安装DjangoRestFramework
pip install djangorestframework==3.9.2
pip install markdown==3.0.1 # Markdown support for the browsable API.
pip install django-filter==2.1.0 # Filtering support
3、DjangoRestFramework 基本使用
from django.contrib import admin
from django.urls import path,re_path,include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
]
urls.py
from django.urls import path,re_path,include
from users import views
urlpatterns = [
re_path(r'info', views.UserInfoViewSet.as_view(), name='user'),
]
users/urls.py
from rest_framework.views import APIView
from django.http import JsonResponse
class UserInfoViewSet(APIView):
def __init__(self):
super(UserInfoViewSet, self).__init__()
def get(self, request, *args, **kwargs):
result = {
'status': True,
'data': 'response data'
}
return JsonResponse(result, status=200)
def post(self, request, *args, **kwargs):
result = {
'status': True,
'data': 'response data'
}
return JsonResponse(result, status=200)
users/views.py
1.2 drf认证&权限 模块 返回顶部
1、authentication基本使用
class UserInfoViewSet(APIView):
authentication_classes = [authentication.IsAuthenticated,] # 用户认证模块
permission_classes = (authentication.IsOwnerOrReadOnly,) # 用户授权模块
from django.contrib import admin
from django.urls import path,re_path,include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
]
urls.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from django.urls import path,re_path,include
from users import views
urlpatterns = [
re_path(r'info', views.UserInfoViewSet.as_view(), name='user'),
]
users/urls.py
from rest_framework.views import APIView
from django.http import JsonResponse
from common.auth import authentication
class UserInfoViewSet(APIView):
authentication_classes = [authentication.IsAuthenticated,]
permission_classes = (authentication.IsOwnerOrReadOnly,)
def __init__(self):
super(UserInfoViewSet, self).__init__()
def get(self, request, *args, **kwargs):
result = {
'status': True,
'data': 'response data'
}
return JsonResponse(result, status=200)
def post(self, request, *args, **kwargs):
result = {
'status': True,
'data': 'response data'
}
return JsonResponse(result, status=200)
users/views.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from rest_framework import authentication
from rest_framework import exceptions
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_permission(self, request, view):
if False: # 这里暂且不进行权限验证
raise exceptions.ParseError('您没有操作的权限')
return True
class IsAuthenticated(authentication.BaseAuthentication):
def authenticate(self, request):
auth = request.META.get('HTTP_AUTHORIZATION', None) # 获取 header中的 Authorization
if auth is None:
raise exceptions.NotAuthenticated()
'''这里应该是验证token是否合法逻辑'''
# token = Token.objects.filter(key=auth)
# try:
# request.user = token[0].user
# except IndexError:
# raise exceptions.NotAuthenticated('Invalid input Authenticated')
return (request, None)
def authenticate_header(self, request):
msg = 'Invalid token.Please get token first'
return exceptions.NotAuthenticated(msg)
common\auth\authentication.py
2、测试接口
1.3 djangorestframework 序列化 返回顶部
1、序列化使用举例(serializers.Serializer)
'''1、ser = UserInfoSerializer(instance=obj,many=True)'''
# 对查询实例进行序列化 # ser.data 获取序列化后的json格式数据
'''2、定义显示的字段''' name = serializers.CharField() # 显示普通字段
ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
from django.contrib import admin
from django.urls import path,re_path,include
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'users/',include(('users.urls', 'users'), namespace='users'))
]
urls.py
'''users/urls.py'''
from django.urls import path,re_path
from users import views
urlpatterns = [
re_path(r'^info/$', views.UserInfoViewSet.as_view(), name='userinfo'),
]
users/urls.py
'''users/models.py'''
from __future__ import unicode_literals
from django.db import models
class UserInfo(models.Model):
name = models.CharField(max_length=64,unique=True)
ut = models.ForeignKey(to='UserType', on_delete=models.CASCADE)
gp = models.ManyToManyField(to='UserGroup')
class UserType(models.Model):
type_name = models.CharField(max_length=64,unique=True)
class UserGroup(models.Model):
group = models.CharField(max_length=64)
users/models.py
''' users/views.py'''
from rest_framework.views import APIView
from rest_framework.views import Response
from users.serializers.userinfo_serializers import UserInfoSerializer
from users.models import UserInfo
class UserInfoViewSet(APIView):
def get(self, request, *args, **kwargs):
obj = UserInfo.objects.all()
ser = UserInfoSerializer(instance=obj,many=True)
# ret = json.dumps(ser.data,ensure_ascii=False)
# return HttpResponse(ret)
return Response(ser.data, status=200)
'''
[{
"name": "zhangsan",
"ut": "学生",
"gp": [{
"id": 1,
"gp": "group01"
}, {
"id": 2,
"gp": "group02"
}],
"xxx": "zhangsan"
}, {
"name": "lisi",
"ut": "学生",
"gp": [{
"id": 1,
"gp": "group01"
}],
"xxx": "lisi"
}]
users/views.py
'''users/serializers/userinfo_serializers.py'''
from rest_framework import serializers
from users.models import UserInfo
class UserInfoSerializer(serializers.Serializer):
name = serializers.CharField() # 显示普通字段
ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
class Meta:
model = UserInfo
def get_gp(self,row):
'''row: 传过来的正是 UserInfo表的对象'''
gp_obj_list = row.gp.all() # 获取用户所有组
ret = []
for item in gp_obj_list:
ret.append({
'id':item.id,'gp':item.group})
return ret
2、序列化使用举例(serializers.ModelSerializer)
1. ModelSerializer本质是继承了Serielizer类添加了部分功能
2. 在使用上ModelSerializer可以使用 fields = ‘__all__‘ 定义要显示的字段
'''users/serializers/userinfo_serializers.py'''
from rest_framework import serializers
from users.models import UserInfo
class UserInfoSerializer(serializers.ModelSerializer):
# name = serializers.CharField() # 显示普通字段
ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
class Meta:
model = UserInfo
# fields = "__all__"
fields = ["name",'ut','gp','xxx'] # 定义显示那些字段
def get_gp(self,row):
'''row: 传过来的正是 UserInfo表的对象'''
gp_obj_list = row.gp.all() # 获取用户所有组
ret = []
for item in gp_obj_list:
ret.append({
'id':item.id,'gp':item.group})
return ret
serializers.ModelSerializer使用
3、使用serializers.ModelSerializer 进行数据验证
from rest_framework.views import APIView
from users.serializers.userinfo_serializers import UserInfoSerializer
from users.models import UserInfo
class UserInfoViewSet(APIView):
def get(self, request, *args, **kwargs):
obj = UserInfo.objects.all()
ser = UserInfoSerializer(instance=obj,many=True)
ret = json.dumps(ser.data,ensure_ascii=False)
return HttpResponse(ret)
def post(self, request, *args, **kwargs):
ser = UserInfoSerializer(data=request.data) # 验证,对请求发来的数据进行验证
if ser.is_valid():
print(ser.validated_data) # post请求数据字典
else:
print(ser.errors) # form验证错误信息
return HttpResponse(json.dumps({
'status':True}))
users/views.py
'''users/serializers/userinfo_serializers.py'''
from rest_framework import serializers
from django.core.exceptions import ValidationError
from users.models import UserInfo
class UserInfoSerializer(serializers.ModelSerializer):
name = serializers.CharField(min_length=10, error_messages={
'required': '该字段必填'}) # 显示普通字段
ut = serializers.CharField(source='ut.type_name',required=False) # 显示一对多字段
gp = serializers.SerializerMethodField(required=False) # 自定义显示(显示多对多)
xxx = serializers.CharField(source='name', required=False) # 也可以自定义显示字段名称
class Meta:
model = UserInfo
# fields = "__all__"
fields = ["name",'ut','gp','xxx'] # 定义显示那些字段
# 局部钩子:
def validate_name(self, value): # value 是name字段提交的值
if value.startswith('sb'): # 不能以sb开头
raise ValidationError('不能以sb开头')
else:
return value
# 全局钩子找到了
def validate(self, value): # value是所有校验通过数据的字典
name = value.get('name')
if False:
raise ValidationError('全局钩子引发异常')
return value
users/serializers/userinfo_serializers.py
'''1、ser.is_valid()'''
# 验证post请求中数据是否合法
'''2、全局校验钩子'''
def validate(self, value): # value是所有校验通过数据的字典
'''3、局部钩子'''
def validate_name(self, value): # value 是name字段提交的值
1.4 djangorestframework 分页 返回顶部
1、分页中基本语法
'''1、实例化一个Paginator对象'''
paginator = Paginator(objs, page_size) # paginator对象
'''2、获取总数量&总页数'''
total_count = paginator.count # 总数量
total = paginator.num_pages # 总页数
'''3、使用objs对象获取指定页数内容'''
objs = paginator.page(page)
'''4、对分页后的数据进行序列化操作'''
serializer = Serializer(objs, many=True) # 序列化操作
2、分页模块使用举例
#!/usr/bin/python
# -*- coding: utf-8 -*-
from django.conf import settings
from rest_framework import status
from django.core.paginator import EmptyPage, Paginator, PageNotAnInteger
from rest_framework.views import Response
def Paginators(objs, request, Serializer):
"""
objs : 实体对象, queryset
request : 请求对象
Serializer : 对应实体对象的类
page_size : 每页显示多少条数据
page : 显示第几页数据
total_count :总共有多少条数据
total :总页数
"""
try:
page_size = int(request.GET.get('page_size', settings.REST_FRAMEWORK['PAGE_SIZE']))
page = int(request.GET.get('page', 1))
except (TypeError, ValueError):
return Response(status=400)
paginator = Paginator(objs, page_size) # paginator对象
total_count = paginator.count
total = paginator.num_pages # 总页数
try:
objs = paginator.page(page)
except PageNotAnInteger:
objs = paginator.page(1)
except EmptyPage:
objs = paginator.page(paginator.num_pages)
serializer = Serializer(objs, many=True) # 序列化操作
return Response(
data={
'detail': serializer.data,
'page': page,
'page_size': page_size,
'total': total,
'total_count': total_count
}
)
common/utils/api_paginator.py 自定义分页模块
# 分页
REST_FRAMEWORK = {
# 全局分页
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 关闭api root页面展示
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
),
'UNICODE_JSON': False,
# 自定义异常处理
'EXCEPTION_HANDLER': (
'common.utils.custom_exception_handler'
),
'PAGE_SIZE': 10
}
settings.py
'''users/serializers/userinfo_serializers.py'''
from rest_framework import serializers
from users.models import UserInfo
class UserInfoSerializer(serializers.Serializer):
name = serializers.CharField() # 显示普通字段
ut = serializers.CharField(source='ut.type_name') # 显示一对多字段
gp = serializers.SerializerMethodField() # 自定义显示(显示多对多)
xxx = serializers.CharField(source='name') # 也可以自定义显示字段名称
class Meta:
model = UserInfo
def get_gp(self,row):
'''row: 传过来的正是 UserInfo表的对象'''
gp_obj_list = row.gp.all() # 获取用户所有组
ret = []
for item in gp_obj_list:
ret.append({
'id':item.id,'gp':item.group})
return ret
users/serializers/userinfo_serializer.py
''' users/views.py'''
from rest_framework.views import APIView
from rest_framework.views import Response
from users.serializers.userinfo_serializers import UserInfoSerializer
from users.models import UserInfo
from common.utils.api_paginator import Paginators
class UserInfoViewSet(APIView):
queryset = UserInfo.objects.all().order_by('id')
serializer_class = UserInfoSerializer
def get(self, request, *args, **kwargs):
self.queryset = self.queryset.all()
ret = Paginators(self.queryset, request, self.serializer_class)
print(json.dumps(ret.data)) # ret.data 返回的是最终查询的json数据
return Response(ret.data)
# http://127.0.0.1:8000/users/info/?page_size=1
'''
{
"detail": [
{
"name": "zhangsan",
"ut": "学生",
"gp": [
{
"id": 1,
"gp": "group01"
},
{
"id": 2,
"gp": "group02"
}
],
"xxx": "zhangsan"
}
],
"page": 1,
"page_size": 1,
"total": 3,
"total_count": 3
}
'''
users/views.py
1.5 JWT:使用djangorestframework-jwt模块进行用户身份验证
安装: pip install djangorestframework-jwt
添加应用:python manage.py users
官方网站:http://getblimp.github.io/django-rest-framework-jwt/#rest-framework-jwt-auth
1、配置使用JWT
########### 1、在INSTALLED_APPS中加入'rest_framework.authtoken', #################
INSTALLED_APPS = [
'''
'rest_framework.authtoken', #
'''
]
################### 2、配置jwt验证 ######################
REST_FRAMEWORK = {
# 身份认证
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
import datetime
JWT_AUTH = {
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
AUTH_USER_MODEL='users.User' # 指定使用users APP中的 model User进行验证
settings.py配置使用JWT
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
username = models.CharField(max_length=64, unique=True)
password = models.CharField(max_length=64)
phone = models.CharField(max_length=64)
token = models.CharField(max_length=255)
users/models.py 添加用户认证的User表
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from rest_framework_jwt.settings import api_settings
from rest_framework import serializers
from users.models import User
class UserSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
phone = serializers.CharField()
token = serializers.CharField(read_only=True)
def create(self, data):
user = User.objects.create(**data)
user.set_password(data.get('password'))
user.save()
# 补充生成记录登录状态的token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user.token = token
return user
users/serializers.py 使用Serializer的create方法创建token
from django.contrib import admin
from django.urls import path,re_path,include
from users import views
from rest_framework_jwt.views import obtain_jwt_token # 验证密码后返回token
urlpatterns = [
path('admin/', admin.site.urls),
path('register/', views.RegisterView.as_view(), name='register'), # 注册用户
path('login/', obtain_jwt_token,name='login'), # 用户登录后返回token
path('user/list/', views.UserList.as_view(), name='register'), # 测试需要携带token才能访问
]
urls.py
import json
from rest_framework.views import APIView
from rest_framework.views import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from users.serializers import UserSerializer
# 用户注册
class RegisterView(APIView):
def post(self, request, *args, **kwargs):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.error, status=400)
# 测试必须携带token才能访问接口
class UserList(APIView):
permission_classes = [IsAuthenticated] # 接口中加权限
authentication_classes = [JSONWebTokenAuthentication]
def get(self,request, *args, **kwargs):
print(request.META.get('HTTP_AUTHORIZATION', None))
return Response({
'name':'zhangsan'})
def post(self,request, *args, **kwargs):
return Response({
'name':'zhangsan'})
users/views.py
# 通过用户token获取用户信息
from rest_framework_jwt.utils import jwt_decode_handler
toke_user = jwt_decode_handler(token)
# {'user_id': 2, 'username': 'lisi', 'exp': 1561504444, 'email': ''}
1111
转载于//www.cnblogs.com/xiaonq/p/10987889.html
还没有评论,来说两句吧...