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,
        },
    }
} 
  1. 记得在 项目 目录下, 新建logs文件夹, 存放日志文件
  2. 修改 .gitignore 添加"logs/*"
  3. 创建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字段 )

  1. 创建、修改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
  1. 自定义的用户模型类还不能直接被Django的认证系统所识别,需要在配置文件中告知Django认证系统使用我们自定义的模型类。
# setting.py

# AUTH_USER_MODEL参数的设置以点.来分隔,表示应用名.模型类名。
AUTH_USER_MODEL = 'users.User'

注意:Django建议我们对于AUTH_USER_MODEL参数的设置一定要在第一次数据库迁移之前就设置好,否则后续使用可能出现未知错误。

  1. 迁移
python manage.py makemigrations
python manage.py migrate

7. 实现 发送短信验证码接口 的一些 小技巧

# 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'})

8. 解决同源策略 -> 跨域CORS

上一篇下一篇

猜你喜欢

热点阅读