DRF项目逻辑收录(一)
2019-03-28 本文已影响0人
battleMonkey
1. app子应用 收录在 同一个文件夹
实现
# setting.py
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 配置sys.path python的系统环境变量, 让django首先搜索 apps这个包路径下的文件
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
...
# 注册子应用
INSTALLED_APPS = [
...
'rest_framework',
]
2. redis 的配置和使用
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
}
# 设置 Django 的 session 使用 redis 引擎 存储
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# 使用名为'session'的redis-1 库 存储 session信息
SESSION_CACHE_ALIAS = "session"
3. 日志设置
复制代码到setting下即可:
# setting.py
# 设置一个相对复杂的 日志配置 模板
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
},
},
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logs/meiduo.log"), # 日志文件的位置
'maxBytes': 300 * 1024 * 1024,
'backupCount': 10,
'formatter': 'verbose'
},
},
'loggers': {
'django': { # 定义了一个名为django的日志器
'handlers': ['console', 'file'],
'propagate': True,
},
}
}
- 之后的收尾工作(不做会有问题呦!)
- 记得在 项目 目录下, 新建logs文件夹, 存放日志文件
- 修改 .gitignore 添加"logs/*"
- 创建logs/.gitkeep , 保证 可以git push 上传 空文件夹
4. 异常处理
1) 新建utils/exceptions.py
处理, 数据库 读取、写入失败的问题
# utils/exceptions.py
from rest_framework.views import exception_handler as drf_exception_handler
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status
# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('meiduo')
def exception_handler(exc, context):
"""
自定义异常处理
:param exc: 异常
:param context: 抛出异常的上下文
:return: Response响应对象
"""
# 调用drf框架原生的异常处理方法
response = drf_exception_handler(exc, context)
if response is None:
view = context['view']
if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
# 数据库异常
logger.error('[%s] %s' % (view, exc))
response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
return response
2) 修改 setting.py, 调用 此 异常处理 文件
# setting.py
REST_FRAMEWORK = {
# 异常处理
'EXCEPTION_HANDLER': 'utils.exceptions.exception_handler',
}
6. 继承 修改 DRF系统 user 模型类( 比如添加 mobile字段 )
- 创建、修改models.py, 使继承 user的AbstractUser类
# apps/users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
"""用户模型类"""
mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
- 自定义的用户模型类还不能直接被Django的认证系统所识别,需要在配置文件中告知Django认证系统使用我们自定义的模型类。
# setting.py
# AUTH_USER_MODEL参数的设置以点.来分隔,表示应用名.模型类名。
AUTH_USER_MODEL = 'users.User'
注意:Django建议我们对于AUTH_USER_MODEL参数的设置一定要在第一次数据库迁移之前就设置好,否则后续使用可能出现未知错误。
- 迁移
python manage.py makemigrations
python manage.py migrate
7. 实现 发送短信验证码接口 的一些 小技巧
- 检查是否在60s内有发送记录
# apps/verifications/views.py
from rest_framework.generics import GenericAPIView
from .serializers import RegisterSMSCodeSerializer
from django_redis import get_redis_connection
from rest_framework.response import Response
from rest_framework import status
from random import randint
from libs.yuntongxun.sms import CCP
class RegisterSMSCodeView(GenericAPIView):
"""
获取短信验证码
GET /verifications/smscodes/(?P<mobile>1[345789]\d{9})/?text=xxxx&image_code_id=xxxx
获取短信验证码,首先需要校验 验证码
思路:
创建序列化器,定义text 和 image_code_id
redis 判断该用户是否频繁获取
生成短信验证码
redis增加记录
发送短信
返回响应
"""
serializer_class = RegisterSMSCodeSerializer
def get(self,request,mobile):
# 创建序列化器, 定义text和image_code_id
serializer = self.get_serializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
# redis
redis_conn = get_redis_connection('code')
"""*****************判断该用户是否频繁获取******************"""
if redis_conn.get('sms_flag_%s'%mobile):
return Response(status=status.HTTP_429_TOO_MANY_REQUESTS)
"""*******************************************************"""
# 生成短信验证码
sms_code = '%06d'%randint(0,999999)
# redis增加记录
redis_conn.setex('sms_%s'%mobile,5*60,sms_code)
"""***************** 设置 标记 Flag******************"""
redis_conn.setex('sms_flag_%s'%mobile,60,1)
"""*************************************************"""
# 发送短信
ccp = CCP()
ccp.send_template_sms(mobile,[sms_code,5],1)
# 返回响应
return Response({'message':'ok'})