dev.py
1 """ 2 Django settings for luffy project. 3 4 Generated by 'django-admin startproject' using Django 2.2.1. 5 6 For more information on this file, see 7 https://docs.djangoproject.com/en/2.2/topics/settings/ 8 9 For the full list of settings and their values, see 10 https://docs.djangoproject.com/en/2.2/ref/settings/ 11 """ 12 13 import os 14 15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 18 # 新增一个系统导包路径 19 import sys 20 sys.path.insert(0,os.path.join(BASE_DIR,"apps")) 21 22 # Quick-start development settings - unsuitable for production 23 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ 24 25 # SECURITY WARNING: keep the secret key used in production secret! 26 SECRET_KEY = '!!t0^(#x0l@!pp6@^!0u5lyq+4ctyui)sxmsc4*r7644@(4uh@' 27 28 # SECURITY WARNING: don't run with debug turned on in production! 29 DEBUG = True 30 31 ALLOWED_HOSTS = [ 32 'api.luffycity.cn', 33 ] 34 35 # CORS组的配置信息 36 CORS_ORIGIN_WHITELIST = ( 37 'www.luffycity.cn:8080', 38 ) 39 # 允许ajax跨域请求时携带cookie 40 CORS_ALLOW_CREDENTIALS = True 41 42 # Application definition 43 44 INSTALLED_APPS = [ 45 'django.contrib.admin', 46 'django.contrib.auth', 47 'django.contrib.contenttypes', 48 'django.contrib.sessions', 49 'django.contrib.messages', 50 'django.contrib.staticfiles', 51 52 # cors跨域组件 53 'corsheaders', 54 'rest_framework', 55 56 'xadmin', 57 'crispy_forms', 58 'reversion', 59 'django_filters', 60 'ckeditor', # 富文本编辑器 61 'ckeditor_uploader', # 富文本编辑器上传图片模块 62 63 64 # 子应用 65 'home', 66 'users', 67 'courses', 68 'cart', 69 'orders', 70 'coupon', 71 'payments', 72 ] 73 74 MIDDLEWARE = [ 75 'corsheaders.middleware.CorsMiddleware', 76 'django.middleware.security.SecurityMiddleware', 77 'django.contrib.sessions.middleware.SessionMiddleware', 78 'django.middleware.common.CommonMiddleware', 79 'django.middleware.csrf.CsrfViewMiddleware', 80 'django.contrib.auth.middleware.AuthenticationMiddleware', 81 'django.contrib.messages.middleware.MessageMiddleware', 82 'django.middleware.clickjacking.XFrameOptionsMiddleware', 83 ] 84 85 ROOT_URLCONF = 'luffy.urls' 86 87 TEMPLATES = [ 88 { 89 'BACKEND': 'django.template.backends.django.DjangoTemplates', 90 'DIRS': [], 91 'APP_DIRS': True, 92 'OPTIONS': { 93 'context_processors': [ 94 'django.template.context_processors.debug', 95 'django.template.context_processors.request', 96 'django.contrib.auth.context_processors.auth', 97 'django.contrib.messages.context_processors.messages', 98 ], 99 }, 100 }, 101 ] 102 103 WSGI_APPLICATION = 'luffy.wsgi.application' 104 105 106 """ 107 自定义用户模型类 108 配置有两项注意的地方: 109 1. 值的格式只能接收两段写法, 必须是 '子应用目录名.模型类名' 110 2. AUTH_USER_MODEL参数的设置一定要在第一次数据库迁移之前就设置好, 111 否则后续使用可能出现未知错误。 112 """ 113 AUTH_USER_MODEL = 'users.User' 114 115 # Database 116 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases 117 118 DATABASES = { 119 # 默认数据库 120 "default": { 121 "ENGINE": "django.db.backends.mysql", 122 "HOST": "127.0.0.1", 123 "PORT": 3306, 124 "USER": "luffy_user", 125 "PASSWORD": "luffy", 126 "NAME": "luffycity", 127 } 128 } 129 130 131 # 缓存配置 132 CACHES = { 133 "default": { 134 "BACKEND": "django_redis.cache.RedisCache", 135 # 项目上线时,需要调整这里的路径 136 "LOCATION": "redis://127.0.0.1:6379/0", 137 138 "OPTIONS": { 139 "CLIENT_CLASS": "django_redis.client.DefaultClient", 140 } 141 }, 142 143 # 存储登录时的极验证验证码 144 "session": { 145 "BACKEND": "django_redis.cache.RedisCache", 146 # 项目上线时,需要调整这里的路径 147 "LOCATION": "redis://127.0.0.1:6379/1", 148 149 "OPTIONS": { 150 "CLIENT_CLASS": "django_redis.client.DefaultClient", 151 } 152 }, 153 154 # 提供存储短信验证码 155 "sms_code": { 156 "BACKEND": "django_redis.cache.RedisCache", 157 "LOCATION": "redis://127.0.0.1:6379/2", 158 "OPTIONS": { 159 "CLIENT_CLASS": "django_redis.client.DefaultClient", 160 } 161 }, 162 163 # 提供存储购物车相关信息 164 "cart": { 165 "BACKEND": "django_redis.cache.RedisCache", 166 "LOCATION": "redis://127.0.0.1:6379/3", 167 "OPTIONS": { 168 "CLIENT_CLASS": "django_redis.client.DefaultClient", 169 } 170 }, 171 } 172 173 # 设置xadmin用户登录时,登录信息session保存到redis 174 SESSION_ENGINE = "django.contrib.sessions.backends.cache" 175 SESSION_CACHE_ALIAS = "session" 176 177 178 # Password validation 179 # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators 180 181 AUTH_PASSWORD_VALIDATORS = [ 182 { 183 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 184 }, 185 { 186 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 187 }, 188 { 189 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 190 }, 191 { 192 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 193 }, 194 ] 195 196 197 # Internationalization 198 # https://docs.djangoproject.com/en/2.2/topics/i18n/ 199 200 LANGUAGE_CODE = 'zh-hans' 201 202 TIME_ZONE = 'Asia/Shanghai' 203 204 USE_I18N = True 205 206 USE_L10N = True 207 208 USE_TZ = False 209 210 211 # Static files (CSS, JavaScript, Images) 212 # https://docs.djangoproject.com/en/2.2/howto/static-files/ 213 214 # 访问静态文件的url地址前缀 215 STATIC_URL = '/static/' 216 217 # 设置django的静态文件目录 218 STATICFILES_DIRS = [ 219 os.path.join(BASE_DIR,"luffy/statics") 220 ] 221 222 # 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错 223 MEDIA_ROOT=os.path.join(BASE_DIR,"luffy/statics") 224 # 访问上传文件的url地址前缀 225 MEDIA_URL ="/media/" 226 227 # 日志配置 228 LOGGING = { 229 'version': 1, 230 'disable_existing_loggers': False, 231 'formatters': { 232 'verbose': { 233 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' 234 }, 235 'simple': { 236 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' 237 }, 238 }, 239 'filters': { 240 'require_debug_true': { 241 '()': 'django.utils.log.RequireDebugTrue', 242 }, 243 }, 244 'handlers': { 245 'console': { 246 'level': 'DEBUG', 247 'filters': ['require_debug_true'], 248 'class': 'logging.StreamHandler', 249 'formatter': 'simple' 250 }, 251 'file': { 252 'level': 'INFO', 253 'class': 'logging.handlers.RotatingFileHandler', 254 # 日志位置,日志文件名,日志保存目录必须手动创建 255 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"), 256 # 日志文件的最大值,这里我们设置300M 257 'maxBytes': 300 * 1024 * 1024, 258 # 日志文件的数量,设置最大日志数量为10 259 'backupCount': 10, 260 # 日志格式:详细格式 261 'formatter': 'verbose' 262 }, 263 }, 264 # 日志对象 265 'loggers': { 266 'django': { 267 'handlers': ['console', 'file'], 268 'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统 269 }, 270 } 271 } 272 273 274 REST_FRAMEWORK = { 275 # 异常处理 276 'EXCEPTION_HANDLER': 'luffy.utils.exceptions.custom_exception_handler', 277 # 配置用户认证方式 278 'DEFAULT_AUTHENTICATION_CLASSES': ( 279 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 280 'rest_framework.authentication.SessionAuthentication', 281 'rest_framework.authentication.BasicAuthentication', 282 ), 283 } 284 285 import datetime 286 JWT_AUTH = { 287 # 配置jwt的有效期 288 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 289 # 设置jwt登录视图的返回值 290 'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler', 291 } 292 293 # 配置django的认证类功能,增加手机号登录 294 AUTHENTICATION_BACKENDS = [ 295 'users.utils.UsernameMobileAuthBackend', 296 ] 297 298 # 极验验证码配置 299 PC_GEETEST_ID = '5f4ab1914455506edffaffd4da37fea5' 300 PC_GEETEST_KEY ='460e13a49d687e5e44e25c383f0473a6' 301 302 303 # 短信配置 304 # 主账号 305 SMS_ACCOUNTSID = '8a216da86ab0b4d2016ab3e05fe400b1' 306 307 # 主账号Token 308 SMS_ACCOUNTTOKEN = '5f0ba4296bbb4e248aa77253ccfe0b31' 309 310 # 创建应用的APPID 311 SMS_APPID = '8a216da86ab0b4d2016ab3e0603900b7' 312 313 # 说明:请求地址,生产环境配置成app.cloopen.com 314 SMS_SERVERIP = 'sandboxapp.cloopen.com' 315 316 317 # 富文本编辑器ckeditor配置 318 CKEDITOR_CONFIGS = { 319 'default': { 320 'toolbar': 'full', # 工具条功能 321 'height': 300, # 编辑器高度 322 # 'width': 300, # 编辑器宽 323 'language':'zh-hans', 324 }, 325 } 326 CKEDITOR_UPLOAD_PATH = '' # 上传图片保存路径,留空则调用django的文件上传功能 327 328 329 # 保利威视频加密服务 330 POLYV_CONFIG = { 331 "userId":"62dc475e3f", 332 "secretkey":"h6FiaEBRMU", 333 "servicesUrl":"https://hls.videocc.net/service/v1/token", 334 } 335 336 337 338 # 支付宝电脑网站支付配置信息 339 ALIPAY_APPID = "2016091600523592" 340 APP_NOTIFY_URL = None 341 ALIPAY_DEBUG = True 342 # APIPAY_GATEWAY="https://openapi.alipay.com/gateway.do" 343 APIPAY_GATEWAY="https://openapi.alipaydev.com/gateway.do" 344 ALIPAY_RETURN_URL = "http://www.luffycity.cn:8080/success" 345 ALIPAY_NOTIFY_URL = "http://api.luffycity.cn:8000/payments/success"
urls.py
1 """luffy URL Configuration 2 3 The `urlpatterns` list routes URLs to views. For more information please see: 4 https://docs.djangoproject.com/en/2.2/topics/http/urls/ 5 Examples: 6 Function views 7 1. Add an import: from my_app import views 8 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 Class-based views 10 1. Add an import: from other_app.views import Home 11 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 Including another URLconf 13 1. Import the include() function: from django.urls import include, path 14 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 """ 16 from django.contrib import admin 17 from django.urls import path,include 18 19 import xadmin 20 xadmin.autodiscover() 21 22 # version模块自动注册需要版本控制的 Model 23 from xadmin.plugins import xversion 24 xversion.register_models() 25 26 from django.urls import re_path 27 from django.conf import settings 28 from django.views.static import serve 29 30 urlpatterns = [ 31 # path('admin/', admin.site.urls), 32 path(r'xadmin/', xadmin.site.urls), 33 # 提供上传文件的浏览服务 34 re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}), 35 path(r'ckeditor/', include('ckeditor_uploader.urls')), 36 path('', include("home.urls")), 37 path('users/', include("users.urls")), 38 path('courses/', include("courses.urls")), 39 path('carts/', include("cart.urls")), 40 path('orders/', include("orders.urls")), 41 path('coupon/', include("coupon.urls")), 42 path('payments/', include("payments.urls")), 43 ]
wsgi.py
1 """ 2 WSGI config for luffy project. 3 4 It exposes the WSGI callable as a module-level variable named ``application``. 5 6 For more information on this file, see 7 https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 """ 9 10 import os 11 12 from django.core.wsgi import get_wsgi_application 13 14 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings') 15 16 application = get_wsgi_application()
pro/pro/utils/公共模型
model.py
1 from django.db import models 2 3 class BaseModel(models.Model): 4 """公共字段模型""" 5 orders = models.IntegerField(null=True, blank=True, verbose_name='显示顺序') 6 is_show=models.BooleanField(verbose_name="是否上架",default=False) 7 is_delete=models.BooleanField(verbose_name="逻辑删除",default=False) 8 create_time = models.DateTimeField(auto_now_add=True,verbose_name="添加时间") 9 update_time = models.DateTimeField(auto_now=True,verbose_name="更新时间") 10 11 class Meta: 12 # 设置当前模型在数据迁移的时候不要为它创建表 13 abstract = True
exceptions.py
1 from rest_framework.views import exception_handler 2 from django.db import DatabaseError 3 from rest_framework.response import Response 4 from rest_framework import status 5 6 import logging 7 logger = logging.getLogger('django') 8 9 def custom_exception_handler(exc, context): 10 """ 11 自定义异常处理 12 :param exc: 异常对象 13 :param context: 抛出异常的上下文环境[异常发生时的相关信息,变量,函数,文件名,模块名] 14 :return: Response响应对象 15 """ 16 # 调用drf框架原生的异常处理方法 17 response = exception_handler(exc, context) 18 19 # 获取异常发生时的视图对象 20 view = context['view'] 21 22 if response is None: 23 24 # 判断是否是数据库操作异常 25 if isinstance( exc, DatabaseError ): 26 logger.error( '[%s] %s' % (view, exc) ) 27 response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) 28 29 return response
home模块
adminx.py
1 import xadmin 2 from xadmin import views 3 4 class BaseSetting(object): 5 """xadmin的基本配置""" 6 enable_themes = True # 开启主题切换功能 7 use_bootswatch = True 8 9 xadmin.site.register(views.BaseAdminView, BaseSetting) 10 11 class GlobalSettings(object): 12 """xadmin的全局配置""" 13 site_title = "路飞学城" # 设置站点标题 14 site_footer = "路飞学城有限公司" # 设置站点的页脚 15 menu_style = "accordion" # 设置菜单折叠 16 17 xadmin.site.register(views.CommAdminView, GlobalSettings) 18 19 20 21 # 轮播图 22 from .models import BannerInfo 23 class BannerInfoModelAdmin(object): 24 list_display=["name","orders","is_show"] 25 xadmin.site.register(BannerInfo, BannerInfoModelAdmin) 26 27 28 # 导航 29 from home.models import NavInfo 30 class NavInfoInfoModelAdmin(object): 31 list_display=["name","link","is_show"] 32 xadmin.site.register(NavInfo, NavInfoInfoModelAdmin)
apps.py
1 from django.apps import AppConfig 2 3 4 class HomeConfig(AppConfig): 5 name = 'home' 6 verbose_name = '我的首页'
models.py
1 from django.db import models 2 from luffy.utils.models import BaseModel 3 # Create your models here. 4 class BannerInfo(BaseModel): 5 """ 6 轮播图 7 """ 8 # upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_to 9 image = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True,blank=True) 10 name = models.CharField(max_length=150, verbose_name='轮播图名称') 11 note = models.CharField(max_length=150, verbose_name='备注信息') 12 link = models.CharField(max_length=150, verbose_name='轮播图广告地址') 13 14 class Meta: 15 db_table = 'ly_banner' 16 verbose_name = '轮播图' 17 verbose_name_plural = verbose_name 18 19 def __str__(self): 20 return self.name 21 22 23 class NavInfo(BaseModel): 24 """ 25 导航 26 """ 27 NAV_POSITION = ( 28 (0, 'top'), 29 (1, 'footer') 30 ) 31 32 name = models.CharField(max_length=50, verbose_name='导航名称') 33 link = models.CharField(max_length=250, verbose_name='导航地址') 34 opt = models.SmallIntegerField(choices=NAV_POSITION, default=0, verbose_name='位置') 35 36 class Meta: 37 db_table = 'ly_nav' 38 verbose_name = '导航' 39 verbose_name_plural = verbose_name 40 41 def __str__(self): 42 return self.name
Serializer.py
1 from rest_framework.serializers import ModelSerializer 2 from .models import BannerInfo 3 class BannerInfoSerializer(ModelSerializer): 4 """轮播图序列化器""" 5 class Meta: 6 model=BannerInfo 7 fields = ("image","link") 8 9 10 from rest_framework.serializers import ModelSerializer 11 from .models import NavInfo 12 class NavInfoSerializer(ModelSerializer): 13 """导航序列化器""" 14 class Meta: 15 model=NavInfo 16 fields = ("name","link")
urls.py
1 from django.urls import path,re_path 2 from . import views 3 urlpatterns = [ 4 path(r"banner/",views.BannerInfoListAPIView.as_view()), 5 path(r"nav/",views.NavInfoAPIView.as_view()), 6 ]
views.py
1 from django.shortcuts import render 2 3 # Create your views here. 4 from rest_framework.generics import ListAPIView 5 from django.db.models import Q 6 from .models import BannerInfo 7 from .serializers import BannerInfoSerializer 8 class BannerInfoListAPIView(ListAPIView): 9 """ 10 轮播图列表 11 """ 12 # queryset = BannerInfo.objects.filter(Q(is_show=True) & Q(is_delete=False)).order_by("-orders") 13 queryset = BannerInfo.objects.filter( is_show=True, is_delete=False ).order_by("-orders") 14 serializer_class = BannerInfoSerializer 15 16 17 18 from .models import NavInfo 19 from .serializers import NavInfoSerializer 20 class NavInfoAPIView(ListAPIView): 21 """ 22 导航列表 23 """ 24 queryset = NavInfo.objects.filter( Q(is_show=True) & Q(is_delete=False) & Q(opt=0) ).order_by("orders") 25 serializer_class = NavInfoSerializer
user模块
apps.py
1 from django.apps import AppConfig 2 3 4 class UsersConfig(AppConfig): 5 name = 'users'
models.py
1 from django.contrib.auth.models import AbstractUser 2 from django.db import models 3 4 class User(AbstractUser): 5 """用户模型类""" 6 mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号') 7 8 class Meta: 9 db_table = 'ly_users' 10 verbose_name = '用户' 11 verbose_name_plural = verbose_name 12 13 14 from luffy.utils.models import BaseModel 15 from courses.models import Course 16 class UserCourse(BaseModel): 17 pay_choices = ( 18 (0, '支付宝'), 19 (1, '微信支付'), 20 (2, '免费活动'), 21 (3, '活动赠品'), 22 (4, '系统赠送'), 23 ) 24 user = models.ForeignKey(User, related_name='user_courses', on_delete=models.DO_NOTHING,verbose_name="用户") 25 course = models.ForeignKey(Course, related_name='course_users', on_delete=models.DO_NOTHING, verbose_name="课程") 26 buy_number = models.CharField(max_length=128, null=True, verbose_name="账单号") 27 buy_type = models.SmallIntegerField(choices=pay_choices, default=0, verbose_name="购买方式") 28 pay_time = models.DateTimeField(null=True, verbose_name="购买时间") 29 out_time = models.DateTimeField(null=True, verbose_name="过期时间") 30 31 class Meta: 32 db_table = 'ly_user_course' 33 verbose_name = '课程购买记录' 34 verbose_name_plural = verbose_name
urls.py
1 from django.urls.conf import path,re_path 2 from rest_framework_jwt.views import obtain_jwt_token 3 from . import views 4 urlpatterns = [ 5 path(r'login/', obtain_jwt_token ), 6 path(r'register/', views.UserAPIView.as_view() ), 7 path(r'captcha/', views.CaptchaAPIView.as_view() ), 8 re_path(r'sms/(?P<mobile>1[3-9]\d{9})/', views.SMSAPIView.as_view() ), 9 re_path(r'(?P<pk>\d+)/orders/',views.UserOrderAPIView.as_view()), 10 ]
utils.py
1 def jwt_response_payload_handler(token, user=None, request=None): 2 """ 3 自定义jwt认证成功返回数据 4 """ 5 return { 6 'token': token, 7 'id': user.id, 8 'username': user.username 9 } 10 11 from django.contrib.auth.backends import ModelBackend 12 from .models import User 13 from django.db.models import Q 14 import re 15 16 def get_user_by_account(account): 17 """根据账号信息获取用户模型""" 18 try: 19 # if re.match('^1[3-9]\d{9}$', account): 20 # # 手机号 21 # user = User.objects.get(mobile=account) 22 # else: 23 # # 用户名 24 # user = User.objects.get(username=account) 25 26 user = User.objects.get(Q(mobile=account) | Q(username=account)) 27 28 except User.DoesNotExist: 29 30 user = None 31 32 return user 33 34 35 class UsernameMobileAuthBackend(ModelBackend): 36 def authenticate(self, request, username=None, password=None, **kwargs): 37 # 进行登录判断 38 39 user = get_user_by_account(username) 40 41 # 账号通过了还要进行密码的验证,以及判断当前站好是否是激活状态 42 if isinstance(user,User) and user.check_password(password) and self.user_can_authenticate(user): 43 return user
views.py
1 from rest_framework.views import APIView 2 from luffy.libs.geetest import GeetestLib 3 from django.conf import settings 4 import random 5 from rest_framework.response import Response 6 from django_redis import get_redis_connection 7 8 class CaptchaAPIView(APIView): 9 """极验验证码""" 10 gt = GeetestLib(settings.PC_GEETEST_ID, settings.PC_GEETEST_KEY) 11 redis = get_redis_connection("default") 12 def get(self,request): 13 """提供生成验证码的配置信息""" 14 user_id = '%06d' % random.randint(1, 9999) 15 status = self.gt.pre_process(user_id) 16 17 # 把这两段数据不要保存在session里面, 保存到redis里面 18 # request.session[self.gt.GT_STATUS_SESSION_KEY] = status 19 # request.session["user_id"] = user_id 20 # 使用django-redis保存流水号和用户标识符 21 22 23 # set(键,值) 设置一个字符串值 24 # setex(键,有效期,值) 设置一个指定有效期的字符串值 25 self.redis.setex(self.gt.GT_STATUS_SESSION_KEY, 10*60, status) 26 self.redis.setex("user_id", 10*60, user_id) 27 28 response_str = self.gt.get_response_str() 29 return Response(response_str) 30 31 def post(self,request): 32 """进行二次验证""" 33 challenge = request.data.get(self.gt.FN_CHALLENGE, '') 34 validate = request.data.get(self.gt.FN_VALIDATE, '') 35 seccode = request.data.get(self.gt.FN_SECCODE, '') 36 37 # status = request.session.get(self.gt.GT_STATUS_SESSION_KEY) 38 # user_id = request.session.get("user_id") 39 # 从redis中获取流水号和用户标识符 40 status = self.redis.get(self.gt.GT_STATUS_SESSION_KEY) 41 user_id = self.redis.get("user_id") 42 43 if status: 44 result = self.gt.success_validate(challenge, validate, seccode, user_id) 45 else: 46 result = self.gt.failback_validate(challenge, validate, seccode) 47 48 # todo 返回一个随机字符串,在用户登录提供数据时一并发送到后端,进行验证 49 50 # 后面可以使用redis保存 51 52 return Response({"message": result}) 53 54 from luffy.libs.yuntongxun.sms import CCP 55 from django_redis import get_redis_connection 56 class SMSAPIView(APIView): 57 # url: users/sms/(?P<mobile>1[3-9]\d{9}) 58 def get(self,request,mobile): 59 redis = get_redis_connection("sms_code") 60 # 获取短信发送间隔 61 try: 62 interval = redis.get("%s_interval" % mobile) 63 if interval: 64 print(interval) 65 return Response({"result":"-1"}) 66 except: 67 pass 68 69 ccp = CCP() 70 sms_code = "%04d" % random.randint(1,9999) 71 result = ccp.send_template_sms(mobile,[sms_code, 5],1) 72 73 if not result: 74 """发送成功""" 75 76 redis.setex("%s_sms_code" % mobile, 5*60, sms_code) 77 # 这里的值不重要,重要的是这个变量是否在redis被查找到 78 redis.setex("%s_interval" % mobile, 60, 1) 79 80 return Response({"result":result}) 81 82 83 from .serializers import UserModelSerializer 84 from rest_framework.generics import CreateAPIView 85 from .models import User 86 class UserAPIView(CreateAPIView): 87 serializer_class = UserModelSerializer 88 queryset = User.objects.all() 89 90 from .serializers import UserOrderModelSerializer 91 from rest_framework.generics import RetrieveAPIView 92 from rest_framework.permissions import IsAuthenticated 93 class UserOrderAPIView(RetrieveAPIView): 94 permission_classes = [IsAuthenticated] 95 serializer_class = UserOrderModelSerializer 96 queryset = User.objects.all()