Django转换器、配置文件作用
# django转换器 2.x以后 为了取代re_path
int path('books/<int:pk>')--->/books/1--->pk=1--->当参数传入视图类的方法中
str path('books/<str:name>')
path path('media/<path:path>',serve,{'document_root':'路径'} ),
slug
uuid
# django配置文件
1.Django项目要运行 优先执行配置文件的内容 做一下配置加载工作 manage.py中
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_day07.settings')
##Django项目配置文件的路径可以修改 配置文件名也可以修改 但一般不会去改
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '配置文件路径')
2.任何一个Django项目都有两套配置
一套是项目自己的 自己有哪个配置参数 优先用自己的
一套是内置的(Django内置的)
3.配置参数的作用
# 1 项目的根路径
BASE_DIR
# 2 密钥---》djagno中涉及到加密的,大部分都会用这个密钥
SECRET_KEY
# 3 是否开启调试模式 上线一定关闭 只要是调试模式,访问路径不存在时,会显示出所有能访问的路径,视图类出了异常,浏览器中能看到
DEBUG = True 默认是True
# 4 项目是要部署在某个服务器上 这个列表写部署服务器的ip地址 *表示任何地址都可以
ALLOWED_HOSTS = ['*'] 默认是空的
# 5 内置 我们自己写的app
INSTALLED_APPS = [
'django.contrib.admin', # 后台管理---》很多表不是它的,是别的app的
'django.contrib.auth', # auth 模块,UsrInfo表----》有6个表
'django.contrib.contenttypes', # 有个django_content_type表是,这个app的
'django.contrib.sessions', # session相关的
'django.contrib.messages', # 消息框架
'django.contrib.staticfiles', # 静态文件开启的app
'app01.apps.App01Config', # app01 自己写的app要在这里注册
'rest_framework' # drf 浏览器访问需要在这里注册
]
# 6 中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # session相关
'django.middleware.common.CommonMiddleware', # 公共
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 7 根路由
ROOT_URLCONF = 'drf_day07.urls' # 默认是urls 也可以改文件名 一般不改
# 8 模板文件所在路径
TEMPLATES = [
...
]
# 9 项目上线,运行application,后面再说
WSGI_APPLICATION = 'drf_day07.wsgi.application'
# 10 数据库配置
DATABASES = {
...
}
# 11 做国际化
LANGUAGE_CODE = 'zh-hans' # 语言
TIME_ZONE = 'Asia/Shanghai' # 时区
USE_I18N = True
USE_L10N = True
USE_TZ = True
# 12 静态文件
STATIC_URL = '/static/'
# 13 表中,默认可以不写id,id主键自增,之前全是AutoField,长度很短
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
登录功能
表模型
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
class UserToken(models.Model):
token = models.CharField(max_length=64)
user = models.OneToOneField(to=UserInfo,on_delete=models.CASCADE)
视图类
class UserView(ViewSet):
@action(methods=['POST'],detail=False)
def login(self,request):
username = request.data.get('username')
password = request.data.get('password')
user_obj = UserInfo.objects.filter(username=username,password=password).first()
if user_obj:
# 登录成功
# 1 生成一个随机字符串 token
token = str(uuid.uuid4())
# 2 把token存到表中 UserToken表有值就更新 没有值就增加
UserToken.objects.update_or_create(user=user_obj,defaults={'token':token})
return Response({'code': 100, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
路由
# 方式一:
path('login/',views.UserView.as_view({'post':'login'})),
# 路由如果这样写 是不需要使用action装饰器
# 方式二:自动生成路由---》视图类中一定要用action装饰器
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user',views.UserView,'user')
urlpatterns = [
path('admin/', admin.site.urls),
# path('',include(router.urls))
]
# http://127.0.0.1:8000/user/login/
urlpatterns += router.urls
认证组件
# APIView执行流程
在视图类的方法之前 执行了三大认证
# 认证:登录认证
登录认证---》控制某个接口必须登录后才能访问
# 认证组件使用步骤(固定用法)
1 写一个类 继承BaseAuthentication
from rest_framework.authentication import BaseAuthentication
2 在类中重写authenticate方法
class LoginAuth(BaseAuthentication):
def authenticate(self, request): # 父类中有 一定要重写 否则报错
# 校验用户是否登录---》请求中携带我给的token 就是登录了
# token在哪携带 是接口规定的
# 1.规定待在请求地址中---》讲这个
# 2.规定带在请求头中(这个多)
# 3.规定待在请求体中
# 取出token META HTTP_TOKEN
'''方法一 从请求地址中取'''
# token = request.query_params.get('token')
'''方法二 从请求头中取'''
token = request.META.get('HTTP_TOKEN')
# 去数据库中 根据token 校验有没有数据
user_token = UserToken.objects.filter(token=token).first()
if user_token:
# 如果有就是已经登录
# print(request.user) 认证没有结束之前不能打印request.user 否则会递归
user = user_token.user
print(user_token.user) # UserInfo object (1)
return user,token
else:
# 说明它带的token不对的
raise AuthenticationFailed('你没有登录,不能访问')
3 在方法中 完成登录认证 如果没有登录则抛异常
4 如果是登录的 返回登录用户和token
5 在视图类中 使用认证类(局部使用)
class BookView(APIView):
authentication_classes = [LoginAuth,]
6 全局使用:
### 重点:不要在配置文件中,导入莫名其妙的包
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'app01.auth.LoginAuth'
],
}
7 全局使用认证后 局部禁用
class UserView(ViewSet):
authentication_classes = [] # 列表置为空就可以
8 认证类的使用顺序
优先用视图类配置的
其次用项目配置文件
最后用drf默认的配置
# 小重点:一旦通过认证 在request中就有当前登录用户 request.user为当前登录用户
def get(self,request):
print(request.user.username,'访问了接口')
权限组件
# 大家都登录了,但有的功能(接口),只有超级管理员能做,有的功能所有登录用户都能做----》这就涉及到权限的设计了
# 权限设计:比较复杂---》有acl,rbac,abac。。。
# 咱们现在只是为了先讲明白,drf的权限组件如何用,咱们先以最简单的为例
查询所有图书:所有登录用户都能访问(普通用户和超级管理员)
没有权限控制
删除图书 只有超级管理员能访问
给其他用户设置的权限
# 权限类的使用步骤
1.写一个类 继承BasePermission
from rest_framework.permissions import BasePermission
2.在类中写方法:has_permission
如果有权限 就返回True
如果没有权限 就返回False
错误信息是self.message='字符串'
class AdminPermission(BasePermission):
def has_permission(self, request, view):
# 如果有权限 就是返回True 没有权限 返回False
# 判断user_type是不是1 根据当前登录用户
# request.user # 就是当前登录用户 一旦来到这里,登录认证就通过了
if request.user.user_type == 1:
return True
else:
# 错误信息
self.message = '你好:%s,你没有权限' % request.user.username
return False
3.局部使用
class BookDetailView(APIView):
permission_classer = [AdminPermission,]
4.全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'app01.permission.AdminPermission'
],
}
5.局部禁用
class BookView(APIView):
permission_classer = []
频率组件
# 限制访问频次
比如某个接口 一分钟只能访问5次 超过了就得等
按ip地址 限制
按用户id 限制
# 频率类的使用步骤
1.写个类 继承:SimpleRateThrottle
2.重写某个方法:get_cache_key
可以返回ip或者用户id
返回什么就以什么做频率限制
3.写一个类属性 随意命名一个名字
scope = 'lqz'
4.在配置文件中配置
'DEFAULT_THROTTLE_RATES': {
'lqz': '3/m' # 一分钟访问3次
},
5.全局用
'DEFAULT_THROTTLE_CLASSES': [
],
6.局部用
class BookView(APIView):
throttle_classes = [MyThrottle]