原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
DRF应用和管理
【DRF配置管理】Django安装DRF框架并生成openapi风格文档
【DRF配置管理】如何实现JWT身份验证
【DRF配置管理】如何使用序列化:验证码、注册和登录
【DRF配置管理】如何结合ORM实现排序、模糊搜索、范围查询
【DRF配置管理】如何在视图类使用get_objects()
【DRF配置管理】如何实现RBAC页面菜单和按钮权限
【DRF配置管理】如何建立coreapi风格api接口文档
【DRF配置管理】如何建立swagger风格api接口文档
文章目录
前言
django使用jwt验证,可以使用的三方库有好几个,结合drf使用的话,建议使用djangorestframework-simplejwt第三方库,能够很好的完成jwt验证。官方推荐djangorestframework-simplejwt。
一、常见用法
1.安装
pip install djangorestframework-simplejwt
2.配置
# settings.py
INSTALLED_APPS = [
...
'rest_framework_simplejwt',
...
]
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
...
}
SIMPLE_JWT = {
# token有效时长(返回的 access 有效时长)
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(seconds=30),
# token刷新的有效时间(返回的 refresh 有效时长)
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(seconds=20),
}
3.路由
# urls.py
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
urlpatterns = [
# 登录
path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('verify/', TokenVerifyView.as_view(), name='token_verify'),
]
二、request.user的使用
1.request.user包含用户数据
# 配置
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication', # 查询数据库
)
views.py中代码
class UserInfoView(ModelViewSet):
"""更新用户信息"""
queryset = UserProfile.objects.all()
serializer_class = WxUserSerializer
def retrieve(self, request, *args, **kwargs):
print(type(self.request.user)) # UserProfile
print(self.request.user.get_username()) # 有值
print(self.request.user.get_username())
print(self.request.user.user_permissions)
print(self.request.user.groups)
print(self.request.user.is_authenticated)
print(type(self.request.user))
serializer = self.get_serializer(self.request.user)
print(serializer.data)
return Response(status=status.HTTP_200_OK,
data={'code': 0,
'msg': 'ok',
'data': serializer.data})
2.request.user不包含用户数据
# 配置
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTTokenUserAuthentication', # 不查询数据库
)
TokenUser 的位置from rest_framework_simplejwt.models import TokenUser
三、验证、注册和登陆
1.路由配置urls.py
# urls.py
from django.conf.urls import url
from django.urls import include, path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView
)
from views import *
urlpatterns = [
# simple jwt 认证接口
path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('verify/', TokenVerifyView.as_view(), name='token_verify'),
path('wx_login/', WxLoginView.as_view()),
path('user_info/', views.UserInfoView.as_view({'post': 'create', "get": "retrieve"}))
]
2.序列化和反序列化(serializer验证)
# serializer.py
from django.contrib.auth import get_user_model
User = get_user_model()
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['name'] = user.username
return token
def validate(self, attrs):
"""
登录返回token和refresh
:param attrs:
:return:
"""
data = super().validate(attrs)
data['token'] = str(data["access"])
return data
class WxUserSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['id', 'nick_name', 'avatar_url', 'gender', "phone"]
3.views.py
# views.py
from django.conf import settings
def code2session_key(code):
API = 'https://api.weixin.qq.com/sns/jscode2session'
params = 'appid=%s&secret=%s&js_code=%s&grant_type=authorization_code' % (
settings.WX_APP_ID, settings.WX_APP_SECRET, code)
url = API + '?' + params
response = requests.get(url=url)
data = json.loads(response.text) # response.json()
return data
class WxLoginView(APIView):
"""
登录和注册
"""
# 认证:跳过JWT token认证
authentication_classes = []
permission_classes = []
@csrf_exempt
def post(self, request):
code = json.loads(request.body.decode('utf-8')).get('code')
if code:
wx_data = code2session_key(code)
print("wx_data", wx_data)
openid = wx_data.get('openid')
# session_key保存到session中,留作后期调用
if openid:
user, flat = UserProfile.objects.get_or_create(openid=openid,
defaults={'unionid': wx_data.get('unionid'),
'session_key': wx_data.get('session_key')})
# 生成token(JWT)
if user:
# payload = {'openid': openid, "id": user.id, 'unionid': unionid}
# token = create_token(payload, timeout=1000 * 24)
token = MyTokenObtainPairSerializer.get_token(user).access_token
print("token", token)
return Response(status=status.HTTP_200_OK,
data={"code": 0,
"msg": "ok",
"user": user.id,
'token': str(token)})
return Response(status=status.HTTP_200_OK,
data={"code": -1,
"msg": "无法登录",
"user": None,
'token': ''})
class UserInfoView(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
GenericViewSet):
"""更新用户信息"""
queryset = UserProfile.objects.all()
serializer_class = WxUserSerializer
def retrieve(self, request, *args, **kwargs):
print(self.request.user.get_username())
print(self.request.user.user_permissions)
print(self.request.user.groups)
print(self.request.user.is_authenticated)
print(type(self.request.user))
serializer = self.get_serializer(self.request.user)
return Response(status=status.HTTP_200_OK,
data={'code': 0,
'msg': 'ok',
'data': serializer.data})
def create(self, request):
try:
seralizer = WXLoginSerializer(data=request.data, instance=request.user)
if seralizer.is_valid():
seralizer.save()
current_clan = UserClan.objects.filter(user=request.user, is_check=True).first()
uc_seralizer = UserClanSerializer(current_clan)
print(seralizer.data)
return Response(status=status.HTTP_200_OK,
data={"code": 0,
"msg": 'ok',
"data": seralizer.data,
'current_clan': uc_seralizer.data})
else:
return Response(status=status.HTTP_200_OK,
data={"code": -10,
"msg": seralizer.errors,
"data": [],
"current_clan": []})
except Exception as e:
print(e)
return Response(status=status.HTTP_200_OK,
data={
'code': -10,
'msg': '错误' + str(e),
'data': []})