本次学习较为紧促,因为之前有做过Django的小项目,所以跳过了一些基础,这次就直接进入Django-rest-framework的学习。
首先我们先把项目建起来
django-admin startproject Tutorial
python manage.py startapp api
然后我们需要把需要的model也给建起来
修改api/models.py如下
from django.db import models
class UserInfo(models.Model):
user_type_choices = (
(1, 'normal'),
(2, 'VIP'),
(3, 'SVIP'),
)
user_type = models.IntegerField(choices=user_type_choices)
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=64)
class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo', on_delete=models.CASCADE)
token = models.CharField(max_length=64)
值得注意的是,Django 2.0 后,models.ForeignKey() 函数 和 models.OneToOneField() 中的 on_delete 参数不再默认为 CASCADE ,而是必须手动写入参数
然后我们执行数据迁移
python manage.py makemigrations
python manage.py migrate
这边我遇到了pycharm数据库显示为空的状况,通过这边文章得到了解决
现在打开db.sqlite3,我们可以往里面添加如下内容
好了,用户表也创建完了,接下来我们需要创建api了
写好view
修改api/views.py如下
具体就是通过判断username和password是否正确,然后通过md5生成token
from django.http import JsonResponse
from rest_framework.views import APIView
from api import models
# 通过md5,对用户名通过时间加密
def md5(user):
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):
# 设置返回的code和msg
ret = {'code': 1000, 'msg': None}
try:
#获取post的data
user = request.POST.get('username')
pwd = request.POST.get('password')
#通过filter拿到唯一的object
obj = models.UserInfo.objects.filter(username=user, password=pwd).first()
#若拿不到则返回obj为none,返回错误代码
if not obj:
ret['code'] = 1001
ret['msg'] = "username or pwd error"
else:
#生成token,创建或者更新到userToken表中
token = md5(user)
models.UserToken.objects.update_or_create(user=obj, defaults={'token':token})
#抓取异常,返回错误代码
except Exception as e:
ret['code'] = 1002
ret['msg'] = "exception error"
#最后post请求会返回一个json
return JsonResponse(ret)
修改Tutorial/urls.py如下
from django.contrib import admin
from django.urls import path
from api import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/auth/', views.AuthView.as_view())
]
那么我们的登陆获取token的雏形就出来了,接下来我们测试一下代码是否能走得通
通过postman
设置好body中的key和value
经过post测试,返回通过
查看数据库中的userToken,发现Token已经生成了,并且相同用户每次post通过后Token将会更新
那么接下来我们就可以做token的认证了
比如说我们现在来一个订单,但这个订单需要通过了认证,才可以获得
那么我们首先创建一个订单的model
在model.py中加入如下
class Order(models.Model):
gender_choices = (
(1, 'man'),
(2, 'woman'),
)
name = models.CharField(max_length=32)
age = models.IntegerField()
gender = models.IntegerField(choices=gender_choices)
content = models.CharField(max_length=64)
再次通过数据迁移更新到数据库中
python manage.py makemigrations
python manage.py migrate
然后在数据库中加入如下数据
准备好数据后,我们开始更新views
我们在views.py下面加入新的class,这边有一篇文章讲解了几种简单的model转化json的方法,可以看一下
class OrderView(APIView):
def get(self, request, *args, **kwargs):
ret = {'code':1000, 'msg':None, 'data':None}
try:
#较为简单的model转化为json方法
orders = models.Order.objects.all().values()
ret['data'] = list(orders)
except Exception as e:
ret['code'] = 1002
ret['msg'] = "exception error"
return JsonResponse(ret)
然后将其加入路由
path('api/v1/order/', views.OrderView.as_view()),
现在我们通过postman就可以返回我们的所需要的orderlist了
好了,那么现在我们就要把认证加入进去
现在我们在views.py中加入认证class
这次需要加入django-rest-framework的生成认证错误的方法,还有基本的认证方法
from rest_framework import exceptions
from rest_framework.authentication import BasicAuthentication
然后我们开始写认证class
Django获取Header中的信息的文章
class Authtication(object):
def authenticate(self, request):
#用META,参数必须前面跟上HTTP_并且全部大写,例如username就为,HTTP_USERNAME
token = request.META.get('HTTP_TOKEN')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
#必须用django-rest-framework自带的exception
#可以直接找到问题并且内部会return掉返回一个问题并且带有detail
raise exceptions.AuthenticationFailed(detail='auth fail')
#在rest framework内部会讲这两个字段赋值给request,以供后续操作使用
#具体可以在下面的OrderView中显示为 request.user = token_obj.user
# request.auth = token_obj
return (token_obj.user, token_obj)
#这个是BasicAuthentication中的方法,return None就行了,算是通过auth
def authenticate_header(self, requst):
pass
然后我们在OrderView中加入认证
class OrderView(APIView):
authentication_classes = [Authtication,]
def get(self, request, *args, **kwargs):
...
这样我们的认证就加好了,接下来我们就通过postman来测试一下
如果我们没有把token加入到Headers,那么将会收到exceptions.AuthenticationFailed(detail=‘auth fail’)的forbid消息
当我们加入Token之后,就可以成功返回正确的数据了
我们以上面的方法,可以获得一个简单的登陆系统,可以简单的以登陆,获得并且刷新token,然后在需要进行认证的view加入认证,通过带有持有token的header的request,完成认证。
实际上本次学习极少用到django-rest-framework的知识,接下来慢慢通过学习来补全这一块知识后,再发一个总结。
接下来得做一个react-native项目的api,
具体实现十分简单
文章列表(list(Article.object.all().values)
, 任何人都看)
文章的增删改查(需要认证
, 任何人都能看,但是增删改查需要认证)
实现简单的注册功能(创建用户
)
实现登陆功能(拿取token
)