补充:axios封装
# 普通使用:安装 ,导入使用
const filmList=reactive({result:[]}) axios.get().then() async function load(){let response=await axios.get('')filmList.result=response.data.results }
# 封装示例:请求发出去之前和响应回来以后,请求头中会携带格式
import axios from "axios"; axios.defaults.baseURL = "http://127.0.0.1:8001/api/v1" const request = axios.create({timeout: 5000,headers: {'Content-Type': "application/json; charset=utf-8"} })
# 请求拦截器:每次发送请求,请求头都会带:Authorization
request.interceptors.request.use(config => {config.headers['Authorization'] = localStorage.getItem("token")return config })
# 响应拦截器:
request.interceptors.response.use(response => {console.log("response ->" + response)let res = response.data // 真正响应头if (res.code === 100) { //自己定制的状态码return response.data} else {Element.Message.error('系统异常,请联系系统管理员')return Promise.reject(response.data.msg)}} )
# 把对象导出:
export default request
# main.js
import http from './lib/http' Vue.prototype.$http = http
# 在某些组件中使用:
this.$http.get("/user/user/", {params: { // get请求参数username: this.searchForm.username,page: this.page,size: this.size}}).then(res => {this.tableData = res.resultsthis.total = res.count})}
后端项目目录调整
# 目录调整成如下结构:
├── luffy_api├── logs/ # 项目运行时/开发时日志目录 - 包├── manage.py # 脚本文件├── luffy_api/ # 项目主应用,开发时的代码保存 - 包├── apps/ # 开发者的代码保存目录,以模块[子应用]为目录保存 - 包├── libs/ # 第三方类库的保存目录[第三方组件、模块] - 包├── settings/ # 配置目录 - 包├── dev.py # 项目开发时的本地配置└── prod.py # 项目上线时的运行配置├── urls.py # 总路由└── utils/ # 多个模块[子应用]的公共函数类库[自己开发的组件]└── scripts/ # 保存项目运营 开发时的脚本文件 - 文件夹
# 创建app:需要来到apps目录下--->以后创建的app,就在apps目录下了
cd luffy_api/apps
python ../../manage.py startapp user
# 注册app:在配置文件中注册app名字即可把配置文件放到了settings下,命名为 dev.py
需要把 apps目录,在settings中加入环境变量:
import sys import os sys.path.insert(0, str(BASE_DIR)) path = os.path.join(BASE_DIR, 'apps') sys.path.insert(0, path)
# 修改其他代码:
# manage.py 内的代码: os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev') # 项目上线,使用wsig.py 跑,现在先改好【目前用不到】 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.pro') # asgi.py 也是关于项目上线,也改好【目前用不到】 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.pro')
# 如果项目不能运行了:
用命令运行看看:python manage.py runserver如果不能运行,就是有问题
如果命令能运行,绿色箭头运行不了,删除,再重新建一个即可
创建mysql用户
# 使用mysql:
root账号和密码,万一泄露,整个数据库就不安全了
创建个用户,这个用户只对当前项目和库有权限
# mysql 创建用户并授权---》5.7
1.管理员连接数据库 : mysql -uroot -p2.创建数据库: create database luffy default charset=utf8;
3.查看用户: select user,host from mysql.user;
4.创建用户,设置权限账号密码:
grant 权限(create, update) on 库.表 to '账号'@'host' identified by '密码'
配置任意ip都可以连入数据库的账户
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';
由于数据库版本的问题,可能本地还连接不上,就给本地用户单独配置
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';
刷新权限 : flush privileges;如果加root用户允许远程链接:
grant all privileges on *.* to 'root'@'%' identified by '1234';
5.使用新创建的用户,登录mysql: mysql -uluffy -p---Luffy123?
用户表创建
# 扩写 auth的user表:
# setting/dev.py 配置用户表 AUTH_USER_MODEL = 'user.User'# models.py from django.db import models from django.contrib.auth.models import AbstractUserclass User(AbstractUser):mobile = models.CharField(max_length=11, unique=True)# 需要pillow包的支持 pip install pillowicon = models.ImageField(upload_to='icons', default='icons/default.png')class Meta:db_table = 'luffy_user' # 修改表名,无论哪个app里都是luffy_userverbose_name = '用户表'verbose_name_plural = verbose_name # 在后台管理显示的表名def __str__(self):return self.username
# 迁移:一定不要忘了注册app 有可能会找不到manage.py 快捷工具
python manage.py makemigrations
python manage.py migrate# 配置使用mysql数据库:
直接使用mysqlclient,就不需要任何操作 pip install mysqlclient
也可以使用pymysql,但是需要打补丁
# 保护用户名密码 os.environ,机器系统的环境变量 # 如果取不到,使用默认值 user = os.environ.get('MS_USER','luffy') pwd = os.environ.get('MS_PWD','Luffy123?') DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'luffy','USER': user,'PASSWORD': pwd,'HOST': 'localhost','PORT': 3306} }
导包爆红问题
# 导入路径:
已经把三个目录加入到环境变量---项目根路径,小luffy_api,apps
from luffy_api.apps.user.models import User from apps.user.models import User from user.models import User #这样写没问题,但是pycharm提示错误
# 解决Pycharm 导包爆红问题:
在文件夹上点右键,做成 source root
# 总结
如果在app内部,就用相对导入
如果在app外部,就从apps路径导起---最短路径
封装logger
# setting/dev.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': {# 打印在控制台上,用的simple'console': {# 实际开发建议使用WARNING'level': 'DEBUG', # 日志级别'filters': ['require_debug_true'],'class': 'logging.StreamHandler','formatter': 'simple'},# 打印在文件中,用的verbose'file': {# 实际开发建议使用ERROR'level': 'ERROR','class': 'logging.handlers.RotatingFileHandler',# 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),# 日志文件的最大值,这里我们设置300M'maxBytes': 300 * 1024 * 1024,# 日志文件的数量,设置最大日志数量为10'backupCount': 10,# 日志格式:详细格式'formatter': 'verbose',# 文件内容编码'encoding': 'utf-8'},},# 日志对象'loggers': {'django': {'handlers': ['console', 'file'],'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统},} }
# utils/common_logger.py import logging logger = logging.getLogger('django')
# 以后再用的位置: from utils.common_logger import logger class TestLoggerView(APIView):def get(self, request):logger.info("info级别")logger.error('error级别')return Response('测试日志')
封装全局异常处理
# utills/common_exceptions.py from rest_framework.views import exception_handler as drf_exception_handler from rest_framework.response import Response from .common_logger import loggerdef exception_handler(exc, context):# 只要执行到这,一定意味着程序出了异常,记录日志resquest = context.get('request')user = resquest.user.id or '未登录用户'path = resquest.get_full_path()view = str(context.get('view'))ip = resquest.META.get('REMOTE_ADDR')error = str(exc)logger.error('用户:[%s],访问路径:[%s],视图类是:[%s],客户端地址:[%s],出错了,错误信息是:[%s]' % (user, path, view, ip, error)) # 尽量详细res = drf_exception_handler(exc, context)# 后续咱们可以更新细粒度的区分异常: 887 886 833 分别代表什么if res: # drf 异常detail = res.data.get('detail') or res.data or '系统异常,请稍后再试'return Response({'code': 999, 'msg': detail})else: # 非drf异常return Response({'code': 888, 'msg': '系统异常:%s' % str(exc)})
# setting/dev.py 全局异常处理 REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'utills.common_exceptions.exception_handler', }
总配置文件dev.py
from pathlib import Path import os import sys# BASE_DIR已经不是项目根路径了--->项目路径下的luffy_api BASE_DIR = Path(__file__).resolve().parent.parent# 把小luffy_api目录加入环境变量 sys.path.insert(0, str(BASE_DIR))# 把apps目录加入环境变量 path = os.path.join(BASE_DIR, 'apps') sys.path.insert(0, path)SECRET_KEY = 'django-insecure-ulid+q0&6jc&*+hdz*)ruv_j4$a3_mhz3635qpq8)2_1)3au(t'DEBUG = TrueALLOWED_HOSTS = []INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework','user','home', ]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware', ]ROOT_URLCONF = 'luffy_api.urls'TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [BASE_DIR / 'templates'],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},}, ]WSGI_APPLICATION = 'luffy_api.wsgi.application'# 保护用户名密码 user = os.environ.get('MS_USER', 'luffy') pwd = os.environ.get('MS_PWD', 'Luffy123?') DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'luffy','USER': user,'PASSWORD': pwd,'HOST': 'localhost','PORT': 3306,} }AUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',}, ]LANGUAGE_CODE = 'en-us'TIME_ZONE = 'UTC'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = TrueSTATIC_URL = '/static/'DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'# 配置用户表 AUTH_USER_MODEL = 'user.User'# 日志的配置 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': {# 打印在控制台上,用的simple'console': {# 实际开发建议使用WARNING'level': 'DEBUG', # 日志级别'filters': ['require_debug_true'],'class': 'logging.StreamHandler','formatter': 'simple'},# 打印在文件中,用的verbose'file': {# 实际开发建议使用ERROR'level': 'ERROR','class': 'logging.handlers.RotatingFileHandler',# 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"),# 日志文件的最大值,这里我们设置300M'maxBytes': 300 * 1024 * 1024,# 日志文件的数量,设置最大日志数量为10'backupCount': 10,# 日志格式:详细格式'formatter': 'verbose',# 文件内容编码'encoding': 'utf-8'},},# 日志对象'loggers': {'django': {'handlers': ['console', 'file'],'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统},} }# 全局异常处理 REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'utills.common_exceptions.exception_handler', }