1、数据库简单设计:
from django.db import models
class UserInfo(models.Model):
user_type_choices =(
(1,'普通用户'),
(2,'VIP用户'),
(3,'SVIP用户'),
)
user_type = models.CharField(max_length=2,choices=user_type_choices) #用户类型
username = models.CharField(max_length=32)#用户明
password = models.CharField(max_length=64)#密码
#定义object方式pycharm代码提示不出来
object =models.Manager()
class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo',on_delete=models.CASCADE) #一对一关系指向UserInfo表
token = models.FileField(max_length=64) #保存token值
# 定义object方式pycharm代码提示不出来
object = models.Manager()
2、views登录
from rest_framework.views import APIView
from django.http import JsonResponse
from API import models
def md5(user):
'''
通过MD5讲user+时间戳加密成MD5字符串
:param user:
:return:
'''
import hashlib
import time
ctime = str(time.time())
m = hashlib.md5(bytes(user,encoding='utf-8'))
m.update(bytes(ctime,encoding='utf-8'))
return m.hexdigest()
class authView(APIView):
def post(self,request,*args,**kwargs):
ret = {'code':1000,'msg':None}
try:
user = request._request.POST.get('username') #从request.method获取用户提交为什么是这样看下面解释
pwd = request._request.POST.get('password')
obj = models.UserInfo.object.filter(username=user,password=pwd).first() #数据库中查找用户
print(obj)
if not obj:
#判断obj是否空如果空则没有查到用户名密码错误!
ret['code'] = 1001
ret['msg'] = '用户名密码错误!'
return JsonResponse(ret)
#登录成功,生成token
token = md5(user)
#保存token 到数据库 updata_or_create方法存在则更新,不存在则创建。
#user字段等于obj刚才查到的用户,token等于我们通过user+时间戳生成的token
models.UserToken.object.update_or_create(user=obj,defaults={'token':token})
ret['token'] = token
ret['msg'] = '登录成功'
except Exception as e:
ret['code'] = 1002
ret['msg'] = '请求异常'+ str(e)
return JsonResponse(ret)
以上views中关于 request取username为什么加_request解释:
第一片中解释了CBV模式中URL中定义的as_view()方法其实先执行的是self.dispatch(),其实这个方法已经对刚开始的request做了封装:
代码流程:
2.1、dispatch内部已经对request进行了重新赋值。那么进入initialize_request中看看做了什么操作。
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
2.2、initialize_request中return了一个新的对象(第一个参数就是原始的request),那么再进入。Request
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
2.3、 其他代码不用看,直接看self._request = request,封装好的request把原始的request放到了带下划线的request中。所有我们views中如果需要用原始的request传递的参数必须像视图中那样写。
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
self._request = request
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
3、urls.py
from API import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/auth/',views.authView.as_view()),
]
总结: 视图类继承rest_framework 的APIView,而APIView继承与Django的view。所有方法都是相同,先调用dispatch,方法。这一堆继承下来,内部添加不不少其他方法。