luffy前后台配置
一 封装logger对象记录日志
在dev.py中添加配置
# 日志相关配置
# 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作
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': {
# 实际开发建议使用WARNING
'level': 'DEBUG',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'file': {
# 实际开发建议使用ERROR
'level': 'INFO',
'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.py中新建record_log.py文件,使用时直接导入logger对象即可。
import logging
logger = logging.getLogger('django')
二 全局异常处理
在drf中,继承了APIView及其子类的视图类,都会有一个全局异常捕获。在self.dispatch()方法中。
只处理了drf异常,django异常需要自己处理,所以重写一个全局处理的方法,并将重写的方法配置在REST_FRAMEWORK配置项中。
在utils文件夹中定义一个globar_exception.py文件
from rest_framework.views import exception_handler as drf_exception_handler
from utils.record_log import logger
from rest_framework.response import Response
def exception_handler(exc, context):
# print(exc, context)
request = context.get('request')
# 没登陆就是AnonymousUser 匿名用户'
# 记录日志 请求用户,请求方式,请求地址,请求时间,请求哪个视图函数
logger.error(f"用户:【{request.user}】 请求方式:【{request.method}】 请求地址:【{request.get_full_path} 请求函数:【{context.get('view')}】")
res = drf_exception_handler(exc, context)
if res:
# 说明是drf的错误
result = Response(data={'code': 999, 'msg': res.data.get('detail', '服务器错误,请联系管理员')})
else:
# django错误
result = Response(data={'code': 888, 'msg': str(exc)})
return result
context参数
在dev.py配置文件中配置
REST_FRAMEWORK = {
# 自定义的全局异常处理
'EXCEPTION_HANDLER': 'utils.global_exception.exception_handler',
}
三 封装Response
drf提供的Response对象,不能很方便的加入code和msg字段,自己封装一个Response类,以后都用我们自己封装的,方便写code和msg。
在utils文件夹中新建一个response.py文件
from rest_framework.response import Response
class APIResponse(Response):
def __init__(self, code=100, msg='成功', status=None,
template_name=None, headers=None,
exception=False, content_type=None, **kwargs):
data = {'code': code, 'msg': msg, **kwargs}
super().__init__(data=data, status=None,
template_name=None, headers=None,
exception=False, content_type=None)
在使用时直接导入APIResponse即可
from utils.response import APIResponse
return APIResponse(code=100,msg='ok',token='xxxxxxxx')
四 数据库配置
1.创建数据库
// 管理员连接数据库
mysql -uroot -p密码
// 创建数据库
create database luffy;
// 查看用户
select user,host,password from mysql.user;
// 5.7往后的版本
select user,host,authentication_string from mysql.user;
在mysql中创建一个用户luffy_user,给用户授予luffy库的所有权限
// 创建luffy_user允许所有ip连接 mima是xxx123
CREATE USER 'luffy_user'@'%' IDENTIFIED BY 'xxx123';
// 创建luffy_user允许所有本机连接 mima是xxx123
CREATE USER 'luffy_user'@'localhost' IDENTIFIED BY 'xxx123';
// 查看mysql库下的user表
select user,host from user;
// 授予从所有ip连接的luffy_user用户对luffy库所有表的所有操作权限
GRANT ALL PRIVILEGES ON luffy.* to 'luffy_user'@'%';
// 授予从本机连接的luffy_user用户对luffy库所有表的所有操作权限
GRANT ALL PRIVILEGES ON luffy.* to 'luffy_user'@'localhost';
flush privileges;
// 删除允许所有ip连接的用户luffy_user
DROP USER 'luffy_user'@'%';
// 删除允许本机连接的用户luffy_user
DROP USER 'luffy_user'@'localhost';
连接MySQL
# 本地连接
mysql -u 用户名 -p
输入密码
示例:
mysql -u luffy_user -p
# 远端连接
mysql -h ip地址 -P 端口号 -u 用户名 -p
输入密码
示例:
mysql -h 192.168.56.1 -P 3306 -u luffy_user -p
在dev.py中配置数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'luffy',
'USER': user,
'PASSWORD': password,
'HOST': '127.0.0.1',
'PORT': 3306
}
}
启动项目会报错,django默认使用mysqlDB操作mysql,mysqlDB这个模块,在python2可以的,在python3中不支持,于是咱们使用pymysql替换,到了django2.0.7以后,如果使用pymysql替换,需要改django的源代码,后期使用mysqlclient,替换pymysql,mysqlclient是mysqlDB的python3.x版本。
安装mysqlclient模块
pip install mysqlclient
从系统环境变量中获取数据库用户名和密码
数据库配置文件中,直接是明文的用户名和密码,可能存在的风险,如果源代码泄露了,数据库用户名密码就泄露,这是不安全的,所以从系统环境变量中取。
注意: 不要用USER,取到的是当前计算机登录用户的用户名。
在dev.py文件中获取到系统环境变量中的键值对,传给数据库配置即可。
USER = os.environ.get('HANDLE_DATA_NAME', 'luffy_user')
PASSWORD = os.environ.get('PASSWORD', 'xxx123')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'luffy',
'USER': USER,
'PASSWORD': PASSWORD,
'HOST': 'localhost',
'PORT': '3306',
}
}
五 user app的User表配置
继承auth_user表扩写
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
phone_num = models.CharField(max_length=11,unique=True,verbose_name='手机号')
# 需要pillow包的支持 ImageField继承了 FileField只存储图片
icon = models.ImageField(upload_to='icon',default='icon/default.png', verbose_name='头像')
class Meta:
db_table = 'luffy_user' # 指定表名
verbose_name = '用户表'
verbose_name_plural = verbose_name
在dev.py中配置
# 自定义User表
# app.表名
AUTH_USER_MODEL = 'user.User'
安装Pillow模块
pip install Pillow
数据库迁移
python manage.py makemigrations
python manage.py migrate
开放media访问
在dev.py中配置media路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
在urls.py中添加media路由
from django.urls import path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('media/<path:path>', serve, kwargs={'document_root': settings.MEDIA_ROOT}),
]
六 前台项目创建和配置
6.1 创建vue3项目
6.2 配置axios
cnpm install axios --save
cnpm install axios vue-axios --save
全局引入axios方法
main.js中
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(VueAxios,axios)
app.mount('#app')
然后在组件中使用
// App.vue
export default {
name: 'App',
methods: {
getList() {
this.axios.get(api).then((response) => {
console.log(response.data)
})
// or
this.$http.get(api).then((response) => {
console.log(response.data)
})
}
}
}
6.3 配置element-plus
安装
cnpm install element-plus --save
完整引入
main.js
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)
6.4 安装bootstrap,jquery
安装
cnpm install jquery --save
cnpm install bootstrap@3 --save
配置
main.js
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
vue.config.js配置
const webpack = require("webpack");
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.$": "jquery",
Popper: ["popper.js", "default"]
})
]
}
};
6.5 安装vue-cookies
安装
cnpm install vue-cookies --save
main.js中配置
app.config.globalProperties.$cookies = cookies
使用
this.$cookies.set(keyname, value, expires)
七 小知识
7.1 mysql使用localhost连接和使用ip地址链接有什么区别?
host代表此用户(root)只能通过localhost的ip访问此数据库。
host:%,表示用户在任何IP段下连接该实例。host:10.0.0.%,表示用户在任何10.0.0.XXX段下所有IP可以连接该实例。
Windows客户端,root用户向一台Host IP为192.168.91.1的MySQL实例发起了TCP/IP连接请求,并且连接成功。之后,就可以对MySQL数据库进行一些数据库操作,如DDL和DML等。
root用户向一台Host IP为127.0.0.1(本机地址)的MySQL实例发起了TCP/IP连接请求。
root用户向本地服务器的MySQL实例发起了TCP/IP连接请求。
socket(套接字)连接方式
Unix域套接字
在Linux和Unix环境下,还可以使用Unix域套接字。Unix域套接字其实不是一个网络协议,所以只能在MySQL客户端和数据库实例在同一台服务器上的情况下使用(本地连接)。
登录实例后查询:
show variables like 'socket';
+---------------+------------------------------------------+
| Variable_name | Value |
+---------------+------------------------------------------+
| socket | /application/mysql-5.6.38/tmp/mysql.sock |
+---------------+------------------------------------------+
或者通过socket文件登录MySQL数据库中
7.2 mysql中utf8和utf8mb4有什么区别?
utf8(utf8mb3的别名 3 字节 UTF-8 统一码编码)
- 仅支持 BMP 字符(不支持补充 字符)
- 每个多字节字符最多需要三个字节。
utf8mb4 字符集(4 字节 UTF-8 统一码编码)
- 支持 BMP 和增补字符。
- 每个多字节字符最多需要四个字节。
MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。
mysql支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。
最初的 UTF-8 格式使用一至六个字节,最大能编码 31 位字符。最新的 UTF-8 规范只使用一到四个字节,最大能编码21位,正好能够表示所有的 17个 Unicode 平面。utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符。
八 前端全局样式和js配置
在assets文件夹下创建css和js文件夹
css文件夹下的global.css
/* 声明全局样式和项目的初始化样式 */
body, h1, h2, h3, h4, h5, h6, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
margin: 0;
padding: 0;
font-size: 15px;
}
a {
text-decoration: none;
color: #333;
}
ul {
list-style: none;
}
table {
border-collapse: collapse; /* 合并边框 */
}
js文件夹下的settings.js文件
export default {
BASE_URL: 'http://127.0.0.1:8000/'
}
main.js加上下面的代码
import '@/assets/css/global.css'
import settings from '@/assets/jss/settings'
// 以后再使用后端接口的地址 使用BASE_URL进行拼接
Vue.prototype.$settings = settings