django rest framework系列02-引入rest使用APIView实现用户登录且保存Token

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,方法。这一堆继承下来,内部添加不不少其他方法。

 

你可能感兴趣的:(Django,rest,framework,django)