python的Django项目后端

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 # 新增一个系统导包路径
 20 import sys
 21 sys.path.insert(0, os.path.join(BASE_DIR, "apps"))
 22 
 23 
 24 # Quick-start development settings - unsuitable for production
 25 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
 26 
 27 # SECURITY WARNING: keep the secret key used in production secret!
 28 SECRET_KEY = 'i3bobljnf8_l&80^vxzdn^sp)tj9c4zdw3v7s^_w!365(lw_bv'
 29 
 30 # SECURITY WARNING: don't run with debug turned on in production!
 31 DEBUG = True
 32 
 33 
 34 # 设置哪些客户端可以通过地址访问到后端
 35 ALLOWED_HOSTS = [
 36     'api.luffycity.cn',
 37 ]
 38 
 39 # CORS组的配置信息---添加白名单
 40 CORS_ORIGIN_WHITELIST = (
 41     'http://www.luffycity.cn:8080',
 42 )
 43 CORS_ALLOW_CREDENTIALS = True  # 允许ajax跨域请求时携带cookie
 44 
 45 
 46 # Application definition
 47 
 48 INSTALLED_APPS = [
 49     'django.contrib.admin',
 50     'django.contrib.auth',
 51     'django.contrib.contenttypes',
 52     'django.contrib.sessions',
 53     'django.contrib.messages',
 54     'django.contrib.staticfiles',
 55 
 56     # 添加cors跨域组件---添加应用
 57     'corsheaders',
 58     'rest_framework',
 59 
 60     'xadmin',
 61     'crispy_forms',
 62     'reversion',
 63     'django_filters',
 64     'ckeditor',  # 富文本编辑器
 65     'ckeditor_uploader',  # 富文本编辑器上传图片模块
 66 
 67     # 子应用
 68     'home',
 69     'users',
 70     'courses',
 71     'cart',
 72     'orders',
 73     'coupon',
 74     'payments',
 75 
 76 ]
 77 
 78 MIDDLEWARE = [
 79     'corsheaders.middleware.CorsMiddleware',    # 添加cors中间件(跨域相关)---中间层设置【必须写在第一个位置】
 80     'django.middleware.security.SecurityMiddleware',
 81     'django.contrib.sessions.middleware.SessionMiddleware',
 82     'django.middleware.common.CommonMiddleware',
 83     'django.middleware.csrf.CsrfViewMiddleware',
 84     'django.contrib.auth.middleware.AuthenticationMiddleware',
 85     'django.contrib.messages.middleware.MessageMiddleware',
 86     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 87 ]
 88 
 89 ROOT_URLCONF = 'luffy.urls'
 90 
 91 TEMPLATES = [
 92     {
 93         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 94         'DIRS': [],
 95         'APP_DIRS': True,
 96         'OPTIONS': {
 97             'context_processors': [
 98                 'django.template.context_processors.debug',
 99                 'django.template.context_processors.request',
100                 'django.contrib.auth.context_processors.auth',
101                 'django.contrib.messages.context_processors.messages',
102             ],
103         },
104     },
105 ]
106 
107 WSGI_APPLICATION = 'luffy.wsgi.application'
108 
109 """
110 自定义用户模型类
111 配置有两项注意的地方:
112     1. 值的格式只能接收两段写法, 必须是 '子应用目录名.模型类名'
113     2. AUTH_USER_MODEL参数的设置一定要在第一次数据库迁移之前就设置好,
114        否则后续使用可能出现未知错误。
115 """
116 
117 AUTH_USER_MODEL = 'users.User'
118 
119 # Database
120 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
121 
122 DATABASES = {
123     # 默认数据库
124     'default': {
125         'ENGINE': 'django.db.backends.mysql',
126         'HOST': '127.0.0.1',
127         'PORT': 3306,
128         'USER': 'luffy_user',
129         'PASSWORD': 'luffy',
130         'NAME': 'luffycity',
131     }
132 }
133 
134 
135 # redis缓存配置
136 CACHES = {
137     # 默认缓存
138     "default": {
139         "BACKEND": "django_redis.cache.RedisCache",
140         # 项目上线时,需要调整这里的路径
141         "LOCATION": "redis://127.0.0.1:6379/0",
142 
143         "OPTION": {
144             "CLIENT_CLASS": "django_redis.client.DefaultClient",
145         }
146     },
147 
148     "session": {
149         "BACKEND": "django_redis.cache.RedisCache",
150         # 项目上线时,需要调整这里的路径
151         "LOCATION": "redis://127.0.0.1:6379/1",
152 
153         "OPTIONS": {
154             "CLIENT_CLASS": "django_redis.client.DefaultClient",
155         }
156     },
157 
158     # 提供存储短信验证码
159     "sms_code": {
160         "BACKEND": "django_redis.cache.RedisCache",
161         "LOCATION": "redis://127.0.0.1:6379/2",
162         "OPTIONS": {
163             "CLIENT_CLASS": "django_redis.client.DefaultClient",
164         }
165     },
166 
167     # 因为购物车中的商品(课程)信息会经常被用户操作,所以为了减轻服务器的压力,可以选择把购物车信息通过redis来存储.
168     "cart": {
169         "BACKEND": "django_redis.cache.RedisCache",
170         "LOCATION": "redis://127.0.0.1:6379/3",
171         "OPTIONS": {
172             "CLIENT_CLASS": "django_redis.client.DefaultClient",
173         }
174     },
175 
176 }
177 
178 # 设置xadmin用户登录时,登录信息session保存到redis
179 SESSION_ENGINE = "django.contrib.sessions.backends.cache"
180 SESSION_CACHE_ALIAS = "session"
181 
182 
183 # Password validation
184 # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
185 
186 AUTH_PASSWORD_VALIDATORS = [
187     {
188         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
189     },
190     {
191         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
192     },
193     {
194         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
195     },
196     {
197         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
198     },
199 ]
200 
201 
202 # Internationalization
203 # https://docs.djangoproject.com/en/2.2/topics/i18n/
204 
205 # 修改使用中文界面
206 LANGUAGE_CODE = 'zh-Hans'
207 
208 # 修改时区
209 TIME_ZONE = 'Asia/Shanghai'
210 
211 USE_I18N = True
212 
213 USE_L10N = True
214 
215 USE_TZ = False
216 
217 
218 # Static files (CSS, JavaScript, Images)
219 # https://docs.djangoproject.com/en/2.2/howto/static-files/
220 
221 # 访问静态文件的url地址前缀
222 STATIC_URL = '/static/'
223 
224 # 设置django的静态文件目录
225 STATICFILES_DIRS = [
226     os.path.join(BASE_DIR, "/statics")
227 ]
228 
229 # 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错
230 MEDIA_ROOT = os.path.join(BASE_DIR, "statics")
231 # print("============", BASE_DIR)
232 # print(MEDIA_ROOT)
233 # 访问上传文件的url地址前缀
234 MEDIA_URL = "/media/"
235 
236 
237 # 日志配置
238 LOGGING = {
239     'version': 1,
240     'disable_existing_loggers': False,
241     'formatters': {
242         'verbose': {
243             'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
244         },
245         'simple': {
246             'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
247         },
248     },
249     'filters': {
250         'require_debug_true': {
251             '()': 'django.utils.log.RequireDebugTrue',
252         },
253     },
254     'handlers': {
255         'console': {
256             'level': 'DEBUG',
257             'filters': ['require_debug_true'],
258             'class': 'logging.StreamHandler',
259             'formatter': 'simple'
260         },
261         'file': {
262             'level': 'INFO',
263             'class': 'logging.handlers.RotatingFileHandler',
264             # 日志位置,日志文件名,日志保存目录必须手动创建
265             'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"),
266             # 日志文件的最大值,这里我们设置300M
267             'maxBytes': 300 * 1024 * 1024,
268             # 日志文件的数量,设置最大日志数量为10
269             'backupCount': 10,
270             # 日志格式:详细格式
271             'formatter': 'verbose'
272         },
273     },
274     # 日志对象
275     'loggers': {
276         'luffy': {
277             'handlers': ['console', 'file'],
278             'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统
279         },
280     }
281 }
282 
283 
284 REST_FRAMEWORK = {
285     # 异常处理
286     'EXCEPTION_HANDLER': 'luffy.utils.exceptions.custom_exception_handler',
287 
288     # 配置JWT
289     'DEFAULT_AUTHENTICATION_CLASSES': (
290         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
291         'rest_framework.authentication.SessionAuthentication',
292         'rest_framework.authentication.BasicAuthentication',
293     ),
294 }
295 
296 
297 import datetime
298 JWT_AUTH = {
299     # 配置jwt的有效期为 1天
300     'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
301     # 设置jwt登录视图的返回值
302     'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
303 
304 }
305 
306 
307 
308 # 配置django的认证类功能,增加手机号码登录
309 AUTHENTICATION_BACKENDS = [
310     'users.utils.UsernameMobileAuthBackend',
311 ]
312 
313 # 极验验证码配置
314 PC_GEETEST_ID = '5f4ab1914455506edffaffd4da37fea5'
315 PC_GEETEST_KEY ='460e13a49d687e5e44e25c383f0473a6'
316 
317 
318 # 短信配置(注册时的短信验证码)
319 # 主账号
320 SMS_ACCOUNTSID = '8a216da86ab0b4d2016abb6209740948'
321 
322 # 主账号Token
323 SMS_ACCOUNTTOKEN = '1fb208011c9a45babb84807fd3af13b7'
324 
325 # 创建应用的APPID
326 SMS_APPID = '8a216da86ab0b4d2016abb6209c8094e'
327 
328 # 说明:请求地址,生产环境配置成app.cloopen.com
329 SMS_SERVERIP = 'sandboxapp.cloopen.com'
330 
331 
332 # 富文本编辑器ckeditor配置
333 CKEDITOR_CONFIGS = {
334     'default': {
335         'toolbar': 'full',  # 工具条功能
336         'height': 300,      # 编辑器高度
337         # 'width': 300,     # 编辑器宽
338     },
339 }
340 CKEDITOR_UPLOAD_PATH = ''  # 上传图片保存路径,留空则调用django的文件上传功能
341 
342 
343 # 保利威视频加密服务
344 POLYV_CONFIG = {
345     "userId": "2ed6a0347e",
346     "secretkey": "ubWpbwKsi8",
347     "servicesUrl": "https://hls.videocc.net/service/v1/token",
348 }
349 
350 
351 # 支付宝电脑网站支付配置信息
352 ALIPAY_APPID = "2016093000628296"   # 应用ID (APPID:2016093000628296)
353 APP_NOTIFY_URL = None   # 应用回调地址[支付成功以后,支付宝返回结果到哪一个地址下面]
354 ALIPAY_DEBUG = True     # APIPAY_GATEWAY="https://openapi.alipay.com/gateway.do"
355 
356 APIPAY_GATEWAY="https://openapi.alipaydev.com/gateway.do"
357 ALIPAY_RETURN_URL = "http://www.luffycity.cn:8080/success"
358 ALIPAY_NOTIFY_URL = "http://api.luffycity.cn:8000/payments/success"

prop.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 # 新增一个系统导包路径
 20 import sys
 21 sys.path.insert(0, os.path.join(BASE_DIR, "apps"))
 22 
 23 
 24 # Quick-start development settings - unsuitable for production
 25 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
 26 
 27 # SECURITY WARNING: keep the secret key used in production secret!
 28 SECRET_KEY = 'i3bobljnf8_l&80^vxzdn^sp)tj9c4zdw3v7s^_w!365(lw_bv'
 29 
 30 # SECURITY WARNING: don't run with debug turned on in production!
 31 DEBUG = True
 32 
 33 
 34 # 设置哪些客户端可以通过地址访问到后端
 35 ALLOWED_HOSTS = [
 36     'api.luffycity.cn',
 37 ]
 38 
 39 # CORS组的配置信息---添加白名单
 40 CORS_ORIGIN_WHITELIST = (
 41     'http://www.luffycity.cn:8080',
 42 )
 43 CORS_ALLOW_CREDENTIALS = True  # 允许ajax跨域请求时携带cookie
 44 
 45 
 46 # Application definition
 47 
 48 INSTALLED_APPS = [
 49     'django.contrib.admin',
 50     'django.contrib.auth',
 51     'django.contrib.contenttypes',
 52     'django.contrib.sessions',
 53     'django.contrib.messages',
 54     'django.contrib.staticfiles',
 55 
 56     # 添加cors跨域组件---添加应用
 57     'corsheaders',
 58     'rest_framework',
 59 
 60     'xadmin',
 61     'crispy_forms',
 62     'reversion',
 63     'django_filters',
 64     'ckeditor',  # 富文本编辑器
 65     'ckeditor_uploader',  # 富文本编辑器上传图片模块
 66 
 67     # 子应用
 68     'home',
 69     'users',
 70     'courses',
 71     'cart',
 72     'orders',
 73     'coupon',
 74     'payments',
 75 
 76 ]
 77 
 78 MIDDLEWARE = [
 79     'corsheaders.middleware.CorsMiddleware',    # 添加cors中间件(跨域相关)---中间层设置【必须写在第一个位置】
 80     'django.middleware.security.SecurityMiddleware',
 81     'django.contrib.sessions.middleware.SessionMiddleware',
 82     'django.middleware.common.CommonMiddleware',
 83     'django.middleware.csrf.CsrfViewMiddleware',
 84     'django.contrib.auth.middleware.AuthenticationMiddleware',
 85     'django.contrib.messages.middleware.MessageMiddleware',
 86     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 87 ]
 88 
 89 ROOT_URLCONF = 'luffy.urls'
 90 
 91 TEMPLATES = [
 92     {
 93         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 94         'DIRS': [],
 95         'APP_DIRS': True,
 96         'OPTIONS': {
 97             'context_processors': [
 98                 'django.template.context_processors.debug',
 99                 'django.template.context_processors.request',
100                 'django.contrib.auth.context_processors.auth',
101                 'django.contrib.messages.context_processors.messages',
102             ],
103         },
104     },
105 ]
106 
107 WSGI_APPLICATION = 'luffy.wsgi.application'
108 
109 """
110 自定义用户模型类
111 配置有两项注意的地方:
112     1. 值的格式只能接收两段写法, 必须是 '子应用目录名.模型类名'
113     2. AUTH_USER_MODEL参数的设置一定要在第一次数据库迁移之前就设置好,
114        否则后续使用可能出现未知错误。
115 """
116 
117 AUTH_USER_MODEL = 'users.User'
118 
119 # Database
120 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
121 
122 DATABASES = {
123     # 默认数据库
124     'default': {
125         'ENGINE': 'django.db.backends.mysql',
126         'HOST': '127.0.0.1',
127         'PORT': 3306,
128         'USER': 'luffy_user',
129         'PASSWORD': 'luffy',
130         'NAME': 'luffycity',
131     }
132 }
133 
134 
135 # redis缓存配置
136 CACHES = {
137     # 默认缓存
138     "default": {
139         "BACKEND": "django_redis.cache.RedisCache",
140         # 项目上线时,需要调整这里的路径
141         "LOCATION": "redis://127.0.0.1:6379/0",
142 
143         "OPTION": {
144             "CLIENT_CLASS": "django_redis.client.DefaultClient",
145         }
146     },
147 
148     "session": {
149         "BACKEND": "django_redis.cache.RedisCache",
150         # 项目上线时,需要调整这里的路径
151         "LOCATION": "redis://127.0.0.1:6379/1",
152 
153         "OPTIONS": {
154             "CLIENT_CLASS": "django_redis.client.DefaultClient",
155         }
156     },
157 
158     # 提供存储短信验证码
159     "sms_code": {
160         "BACKEND": "django_redis.cache.RedisCache",
161         "LOCATION": "redis://127.0.0.1:6379/2",
162         "OPTIONS": {
163             "CLIENT_CLASS": "django_redis.client.DefaultClient",
164         }
165     },
166 
167     # 因为购物车中的商品(课程)信息会经常被用户操作,所以为了减轻服务器的压力,可以选择把购物车信息通过redis来存储.
168     "cart": {
169         "BACKEND": "django_redis.cache.RedisCache",
170         "LOCATION": "redis://127.0.0.1:6379/3",
171         "OPTIONS": {
172             "CLIENT_CLASS": "django_redis.client.DefaultClient",
173         }
174     },
175 
176 }
177 
178 # 设置xadmin用户登录时,登录信息session保存到redis
179 SESSION_ENGINE = "django.contrib.sessions.backends.cache"
180 SESSION_CACHE_ALIAS = "session"
181 
182 
183 # Password validation
184 # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
185 
186 AUTH_PASSWORD_VALIDATORS = [
187     {
188         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
189     },
190     {
191         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
192     },
193     {
194         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
195     },
196     {
197         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
198     },
199 ]
200 
201 
202 # Internationalization
203 # https://docs.djangoproject.com/en/2.2/topics/i18n/
204 
205 # 修改使用中文界面
206 LANGUAGE_CODE = 'zh-Hans'
207 
208 # 修改时区
209 TIME_ZONE = 'Asia/Shanghai'
210 
211 USE_I18N = True
212 
213 USE_L10N = True
214 
215 USE_TZ = False
216 
217 
218 # Static files (CSS, JavaScript, Images)
219 # https://docs.djangoproject.com/en/2.2/howto/static-files/
220 
221 # 访问静态文件的url地址前缀
222 STATIC_URL = '/static/'
223 
224 # 设置django的静态文件目录
225 STATICFILES_DIRS = [
226     os.path.join(BASE_DIR, "statics")
227 ]
228 
229 # 收集静态文件 -----------------------------------------------------------------------------
230 STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
231 
232 # 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错
233 MEDIA_ROOT = os.path.join(BASE_DIR, "statics")
234 # print("============", BASE_DIR)
235 # print(MEDIA_ROOT)
236 # 访问上传文件的url地址前缀
237 MEDIA_URL = "/media/"
238 
239 
240 # 日志配置
241 LOGGING = {
242     'version': 1,
243     'disable_existing_loggers': False,
244     'formatters': {
245         'verbose': {
246             'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
247         },
248         'simple': {
249             'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
250         },
251     },
252     'filters': {
253         'require_debug_true': {
254             '()': 'django.utils.log.RequireDebugTrue',
255         },
256     },
257     'handlers': {
258         'console': {
259             'level': 'DEBUG',
260             'filters': ['require_debug_true'],
261             'class': 'logging.StreamHandler',
262             'formatter': 'simple'
263         },
264         'file': {
265             'level': 'INFO',
266             'class': 'logging.handlers.RotatingFileHandler',
267             # 日志位置,日志文件名,日志保存目录必须手动创建
268             'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"),
269             # 日志文件的最大值,这里我们设置300M
270             'maxBytes': 300 * 1024 * 1024,
271             # 日志文件的数量,设置最大日志数量为10
272             'backupCount': 10,
273             # 日志格式:详细格式
274             'formatter': 'verbose'
275         },
276     },
277     # 日志对象
278     'loggers': {
279         'luffy': {
280             'handlers': ['console', 'file'],
281             'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统
282         },
283     }
284 }
285 
286 
287 REST_FRAMEWORK = {
288     # 异常处理
289     'EXCEPTION_HANDLER': 'luffy.utils.exceptions.custom_exception_handler',
290 
291     # 配置JWT
292     'DEFAULT_AUTHENTICATION_CLASSES': (
293         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
294         'rest_framework.authentication.SessionAuthentication',
295         'rest_framework.authentication.BasicAuthentication',
296     ),
297 }
298 
299 
300 import datetime
301 JWT_AUTH = {
302     # 配置jwt的有效期为 1天
303     'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
304     # 设置jwt登录视图的返回值
305     'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
306 
307 }
308 
309 
310 
311 # 配置django的认证类功能,增加手机号码登录
312 AUTHENTICATION_BACKENDS = [
313     'users.utils.UsernameMobileAuthBackend',
314 ]
315 
316 # 极验验证码配置
317 PC_GEETEST_ID = '5f4ab1914455506edffaffd4da37fea5'
318 PC_GEETEST_KEY ='460e13a49d687e5e44e25c383f0473a6'
319 
320 
321 # 短信配置(注册时的短信验证码)
322 # 主账号
323 SMS_ACCOUNTSID = '8a216da86ab0b4d2016abb6209740948'
324 
325 # 主账号Token
326 SMS_ACCOUNTTOKEN = '1fb208011c9a45babb84807fd3af13b7'
327 
328 # 创建应用的APPID
329 SMS_APPID = '8a216da86ab0b4d2016abb6209c8094e'
330 
331 # 说明:请求地址,生产环境配置成app.cloopen.com
332 SMS_SERVERIP = 'sandboxapp.cloopen.com'
333 
334 
335 # 富文本编辑器ckeditor配置
336 CKEDITOR_CONFIGS = {
337     'default': {
338         'toolbar': 'full',  # 工具条功能
339         'height': 300,      # 编辑器高度
340         # 'width': 300,     # 编辑器宽
341     },
342 }
343 CKEDITOR_UPLOAD_PATH = ''  # 上传图片保存路径,留空则调用django的文件上传功能
344 
345 
346 # 保利威视频加密服务
347 POLYV_CONFIG = {
348     "userId": "2ed6a0347e",
349     "secretkey": "ubWpbwKsi8",
350     "servicesUrl": "https://hls.videocc.net/service/v1/token",
351 }
352 
353 
354 # 支付宝电脑网站支付配置信息
355 ALIPAY_APPID = "2016093000628296"   # 应用ID (APPID:2016093000628296)
356 APP_NOTIFY_URL = None   # 应用回调地址[支付成功以后,支付宝返回结果到哪一个地址下面]
357 ALIPAY_DEBUG = True     # APIPAY_GATEWAY="https://openapi.alipay.com/gateway.do"
358 
359 APIPAY_GATEWAY="https://openapi.alipaydev.com/gateway.do"
360 ALIPAY_RETURN_URL = "http://www.luffycity.cn:8080/success"
361 ALIPAY_NOTIFY_URL = "http://api.luffycity.cn:8000/payments/success"
362 
363 
364 
365 
366 
367 # print("BASE_DIR 的路径:", BASE_DIR)
368 # # BASE_DIR 的路径: /home/moluo/Desktop/Typory笔记/day84/luffy/luffy
369 #
370 # print("os.path.dirname(BASE_DIR) 的路径:", os.path.dirname(BASE_DIR))
371 # # os.path.dirname(BASE_DIR) 的路径: /home/moluo/Desktop/Typory笔记/day84/luffy
372 #
373 # print("STATIC_ROOT 的路径:", STATIC_ROOT)
374 # # STATIC_ROOT 的路径: /home/moluo/Desktop/Typory笔记/day84/luffy/static

 

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")
 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 
17 from django.urls import re_path, path, include
18 from django.conf import settings
19 from django.views.static import serve
20 
21 import xadmin
22 xadmin.autodiscover()
23 
24 # version模块自动注册需要版本控制的 Model
25 from xadmin.plugins import xversion
26 xversion.register_models()
27 
28 
29 urlpatterns = [
30     # path('admin/', admin.site.urls),
31     path(r'xadmin/', xadmin.site.urls),
32     re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
33     path(r'ckeditor/', include('ckeditor_uploader.urls')),
34     path('', include("home.urls")),
35     path('users/', include("users.urls")),
36     path('courses/', include("courses.urls")),
37     path('carts/', include("cart.urls")),
38     path('orders/', include("orders.urls")),
39     path('coupon/', include("coupon.urls")),
40     path('payments/', include("payments.urls")),
41 
42 ]

 

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 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.prop')
16 
17 application = get_wsgi_application()

manage.py

 1 #!/usr/bin/env python
 2 """Django's command-line utility for administrative tasks."""
 3 import os
 4 import sys
 5 
 6 
 7 def main():
 8     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.prop')
 9     try:
10         from django.core.management import execute_from_command_line
11     except ImportError as exc:
12         raise ImportError(
13             "Couldn't import Django. Are you sure it's installed and "
14             "available on your PYTHONPATH environment variable? Did you "
15             "forget to activate a virtual environment?"
16         ) from exc
17     execute_from_command_line(sys.argv)
18 
19 
20 if __name__ == '__main__':
21     main()

 

pro/pro/utils/公共模型

model.py

 1 from django.db import models
 2 
 3 
 4 class BaseModel(models.Model):
 5     """公共字段模型"""
 6     orders = models.IntegerField(verbose_name='显示顺序', null=True, blank=True)
 7     
 8     is_show = models.BooleanField(verbose_name="是否上架", default=False)
 9 
10     is_delete = models.BooleanField(verbose_name="逻辑删除", default=False)
11 
12     create_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
13 
14     update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
15 
16     class Meta:
17         # 设置当前模型在数据迁移的时候不要为它创建表
18         abstract = True

 

exceptions.py

 1 from rest_framework.views import exception_handler
 2 
 3 from django.db import DatabaseError
 4 from rest_framework.response import Response
 5 from rest_framework import status
 6 
 7 import logging
 8 logger = logging.getLogger('luffy')
 9 
10 def custom_exception_handler(exc, context):
11     """
12     自定义异常处理
13     :param exc: 异常类
14     :param context: 抛出异常的上下文
15     :return: Response 响应对象
16     """
17     # 调用drf框架原声的异常处理方法
18     response = exception_handler(exc, context)
19 
20     if response is None:
21         view = context['view']
22         if isinstance(exc, DatabaseError):
23             # 数据库异常
24             logger.error('[%s] %s' % (view, exc))
25             response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
26 
27     return response

 

 

 

home模块

adminx.py

 1 import xadmin
 2 from xadmin import views
 3 
 4 
 5 class BaseSetting(object):
 6     """xadmin的基本配置"""
 7     enable_themes = True  # 开启主题切换功能
 8     use_bootswatch = True
 9 
10 
11 # ###
12 
13 
14 xadmin.site.register(views.BaseAdminView, BaseSetting)
15 
16 
17 class GlobalSettings(object):
18     """xadmin的全局配置"""
19     site_title = "路飞学城"  # 设置站点标题
20     site_footer = "路飞学城有限公司"  # 设置站点的页脚
21     menu_style = "accordion"  # 设置菜单折叠
22 
23 
24 xadmin.site.register(views.CommAdminView, GlobalSettings)
25 
26 # 轮播图
27 from .models import BannerInfo
28 
29 
30 class BannerInfoModelAdmin(object):
31     list_display = ["name", "orders", "is_show"]
32 
33 
34 xadmin.site.register(BannerInfo, BannerInfoModelAdmin)
35 
36 
37 # 导航
38 from home.models import NavInfo
39 
40 
41 class NavInfoInfoModelAdmin(object):
42     list_display = ["name", "link", "is_show"]
43 
44 
45 xadmin.site.register(NavInfo, NavInfoInfoModelAdmin)

__init__.py

 1 default_app_config = "home.apps.HomeConfig" 

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 
 5 
 6 class BannerInfo(BaseModel):
 7     """
 8     轮播图
 9     """
10     # upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_to
11     image = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True,blank=True)
12     name = models.CharField(max_length=150, verbose_name='轮播图名称')
13     note = models.CharField(max_length=150, verbose_name='备注信息')
14     link = models.CharField(max_length=150, verbose_name='轮播图广告地址')
15 
16     class Meta:
17         db_table = 'ly_banner'
18         verbose_name = '轮播图'
19         verbose_name_plural = verbose_name
20 
21     def __str__(self):
22         return self.name
23 
24 
25 class NavInfo(BaseModel):
26     """
27     导航
28     """
29     NAV_POSITION = (
30         (0, 'top'),
31         (1, 'footer')
32     )
33 
34     name = models.CharField(max_length=50, verbose_name='导航名称')
35     link = models.CharField(max_length=250, verbose_name='导航地址')
36     opt = models.SmallIntegerField(choices=NAV_POSITION, default=0, verbose_name='位置')
37 
38     class Meta:
39         db_table = 'ly_nav'
40         verbose_name = '导航'
41         verbose_name_plural = verbose_name
42 
43     def __str__(self):
44         return self.name

 

Serializer.py

 1 from rest_framework.serializers import ModelSerializer
 2 from .models import BannerInfo
 3 
 4 
 5 class BannerInfoSerializer(ModelSerializer):
 6     """轮播图序列化器"""
 7 
 8     class Meta:
 9         model = BannerInfo
10         fields = ("image", "link")
11 
12 
13 from rest_framework.serializers import ModelSerializer
14 from .models import NavInfo
15 
16 
17 class NavInfoSerializer(ModelSerializer):
18     """导航序列化器"""
19 
20     class Meta:
21         model = NavInfo
22         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 
 9 
10 class BannerInfoListAPIView(ListAPIView):
11     """
12     轮播图列表
13     """
14     # queryset = BannerInfo.objects.filter(Q(is_show=True) & Q(is_delete=False)).order_by("-orders")
15     queryset = BannerInfo.objects.filter(is_show=True, is_delete=False).order_by("-orders")
16     serializer_class = BannerInfoSerializer
17 
18 
19 from .models import NavInfo
20 from .serializers import NavInfoSerializer
21 
22 
23 class NavInfoAPIView(ListAPIView):
24     """
25     导航列表
26     """
27     queryset = NavInfo.objects.filter(Q(is_show=True) & Q(is_delete=False) & Q(opt=0)).order_by("orders")
28     serializer_class = NavInfoSerializer

 

 

users模块

apps.py

1 from django.apps import AppConfig
2 
3 
4 class UsersConfig(AppConfig):
5     name = 'users'
6     verbose_name = '我的用户'

 

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 
 3 from rest_framework_jwt.views import obtain_jwt_token
 4 
 5 from . import views
 6 
 7 urlpatterns = [
 8 
 9     # path(r'authorizations/', obtain_jwt_token, name='authorizations'),
10     path(r'login/', obtain_jwt_token),
11     path(r'captcha/', views.CaptchaAPIView.as_view()),
12     re_path(r'sms/(?P<mobile>1[3-9]\d{9})/', views.SMSAPIView.as_view()),
13     path(r'register/', views.UserAPIView.as_view()),
14     re_path(r'(?P<pk>\d+)/orders/', views.UserOrderAPIView.as_view()),
15 
16 ]

 

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 
12 from django.contrib.auth.backends import ModelBackend
13 from .models import User
14 from django.db.models import Q
15 import re
16 
17 def get_user_by_account(account):
18     """根据账号信息获取用户模型"""
19     try:
20         """
21         # if re.match('^1[3-9]\d{9}$', account):
22         #     # 手机号
23         #     user = User.objects.get(mobile=account)
24         # else:
25         #     # 用户名
26         #     user = User.objects.get(username=account)
27         """
28         user = User.objects.get(Q(mobile=account) | Q(username=account))
29 
30     except User.DoesNotExist:
31         user = None
32 
33     return user
34 
35 
36 class UsernameMobileAuthBackend(ModelBackend):
37     def authenticate(self, request, username=None, password=None, **kwargs):
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 django.shortcuts import render
 2 
 3 # Create your views here.
 4 from .serializers import UserModelSerializer
 5 from rest_framework.generics import CreateAPIView
 6 from .models import User
 7 
 8 
 9 class UserAPIView(CreateAPIView):
10     serializer_class = UserModelSerializer
11     queryset = User.objects.all()
12 
13 
14 from rest_framework.views import APIView
15 from luffy.libs.geetest import GeetestLib
16 from django.conf import settings
17 import random
18 from rest_framework.response import Response
19 
20 
21 class CaptchaAPIView(APIView):
22     """极验验证码"""
23     gt = GeetestLib(settings.PC_GEETEST_ID, settings.PC_GEETEST_KEY)
24 
25     def get(self, request):
26         """提供生成验证码的配置信息"""
27         user_id = '%06d' % random.randint(1, 9999)
28         status = self.gt.pre_process(user_id)
29         print(status)
30 
31         # 把这两段数据不要保存在session里面, 保存到redis里面
32         request.session[self.gt.GT_STATUS_SESSION_KEY] = status
33         request.session["user_id"] = user_id
34 
35         response_str = self.gt.get_response_str()
36         return Response(response_str)
37 
38     def post(self, request):
39         """进行二次验证"""
40         challenge = request.data.get(self.gt.FN_CHALLENGE, '')
41         validate = request.data.get(self.gt.FN_VALIDATE, '')
42         seccode = request.data.get(self.gt.FN_SECCODE, '')
43 
44         status = request.session.get(self.gt.GT_STATUS_SESSION_KEY)
45         user_id = request.session.get("user_id")
46 
47         if status:
48             result = self.gt.success_validate(challenge, validate, seccode, user_id)
49         else:
50             result = self.gt.failback_validate(challenge, validate, seccode)
51 
52         # 返回一个随机字符串,在用户登录提供数据时一并发送到后端,进行验证
53         # 后面可以使用redis保存
54 
55         return Response({"message": result})
56 
57 
58 from luffy.libs.yuntongxun.sms import CCP
59 from django_redis import get_redis_connection
60 
61 
62 class SMSAPIView(APIView):
63     # url:users/ams/(?P<mobile>1[3-9]\d{9})
64     def get(self, request, mobile):
65         redis = get_redis_connection("sms_code")
66         # 获取短信发送间隔
67         try:
68             # interval = redis.get("%s_interval" % mobile)
69             interval = redis.get("%s_sms_code" % mobile)
70             if interval:
71                 print(interval)
72                 return Response({"result": "-1"})
73         except:
74             pass
75 
76         ccp = CCP()
77         sms_code = "%04d" % random.randint(1, 9999)
78         result = ccp.send_template_sms(mobile, [sms_code, 5], 1)
79 
80         if not result:
81             """发送成功"""
82             # 验证码5分钟内有效
83             redis.setex("%s_sms_code" % mobile, 1 * 60, sms_code)
84             # 这里的值不重要,重要的是这个变量是否在redis被查找到
85             # redis.setex("%s_interval" % mobile, 60, 1)
86 
87         return Response({"result": result})
88 
89 
90 from .serializers import UserOrderModelSerializer
91 from rest_framework.generics import RetrieveAPIView
92 from rest_framework.permissions import IsAuthenticated
93 
94 
95 class UserOrderAPIView(RetrieveAPIView):
96     permission_classes = [IsAuthenticated]
97     serializer_class = UserOrderModelSerializer
98     queryset = User.objects.all()

 

posted @ 2019-08-01 23:53  码崽  阅读(880)  评论(0编辑  收藏  举报