DRF,全称Django Restful Framework,是一个基于Django的Restful接口框架,是主要用来做API接口的,为前端提供数据的接口。在前面一片博客中,我们构建了一个vue的项目,vue项目是一个前端项目,这个前端项目中的数据就是接口获取的,而今天要完成的drf项目,就是为vue项目提供数据做接口的,我们把前端vue项目和后端drf项目加在一起,就可以完成一个前后端分离的web项目。
一、搭建虚拟环境
在之前的所有代码或者说项目里,都是使用的windows下全局的一个python环境,比如说我们做一个爬虫项目,本来就只需要request的关于爬虫的模块,但由于用的是全局的python环境,这个环境下不止这些关于爬虫的模块,还有很多其他无关的模块。一是会让这个项目很庞大,很多无关的模块存在,二是项目不好转移,意思就是,我把项目共享出去,或者发给其他人使用,他到底需要安装些什么模块就可以让项目跑起来,总不能让别人把我全局python下的所有模块都安装上吧,那这就有点荒唐了;三是,就算你知道这个项目需要些啥模块,但你知道别人安装模块的版本号???版本号不一样,项目照样运行不起来的。所以我们要给每个项目分配对应的虚拟环境,把当前项目所需要的模块及其版本进行隔离包装到一个虚拟环境中既可。
1,安装
pip install virtualenv
pip install virtualenv-clone
pip install virtualenvwrapper
pip install virtualenvwrapper-win
#这些命令只适用于Windows系统
2,常用命令
创建虚拟环境: mkvirtualenv 虚拟环境名称
创建虚拟环境(指定python版本): mkvirtualenv -p python 虚拟环境名称
查看所有虚拟环境: workon+2次tab键
使用虚拟环境: workon 虚拟环境名称
退出虚拟环境: deactivate
删除虚拟环境(必须先退出虚拟环境内部才能删除当前虚拟环境):
rmvirtualenv 虚拟环境名称
其他相关命令:
查看虚拟环境中安装的包: pip freeze 或者 pip list
收集当前环境中安装的包及其版本: pip freeze > requirements.txt
在部署项目的服务器中安装项目使用的模块: pip install -r requirements.txt
虚拟环境只会管理环境内部的模块和python解析器,对于源代码是毫无关系的
3,创建虚拟环境
把安装的四条命令输入到cmd里,就安装好。然后再cmd中输入mkvirtualenv lufei,这样我就创建了一个叫lufei的虚拟环境。
输入:workon lufei,就进入到lufei的虚拟环境中。标志是:虚拟环境名会在命令行的最左边括号包起来
4,在lufei虚拟环境中安装项目需要的模块
这是一个基于django的restful framework,使用的是mysql数据库,所以首先我们的安装这四个模块
pip install django
pip install PymySQL
pip install Pillow
pip install djangorestframework
切记哈,这四条命令要在lufei的虚拟环境中安装,不然就安装到全局的python环境了,所以安装的时候一定要确认最左边有没有虚拟环境的名字。
5,新建的虚拟环境的位置
二、创建一个django项目
1,创建项目
上面已经说过了,虚拟环境跟源代码是没有关系的,所以我们在任何地方创建Django项目都可以,最后在pycharm打开django项目,然后把环境换成虚拟环境就行了。
比如说我想在'D:\数据'目录下创建一个django项目,我们用cmd切换目录来到这个目录下:
也可以直接在'D:\数据'中,空白处,shift+鼠标右键(win10的操作),选中powershell(这个是和cmd一样的终端),也可以直接到目标目录下:
然后输入命令:django-admin startproject lufei ,这样就创建了一个名叫lufei的django项目
现在,我们就可以在文件夹中看到新建的这个django项目了:
2,配置虚拟环境
现在我们用pycharm打开这个项目,然后点击file,在选中settings:
点击右上角的图标,选中add:
这样就找到了我们之前创建的那个叫lufei的虚拟环境了
这样我们就把当前项目的虚拟环境切换成功了。现在你看到安装的模块只有虚拟环境中的模块,而不是全局python下的所有模块。
三、项目配置
1,目录调整
我们应该把目录调整成这样的:
docs文件夹:项目相关资料保存目录
logs文件夹:项目运行或开发时的日志目录
lufei_drf文件夹:代码保存目录
apps文件夹:开发者的代码保存目录,主要是子应用代码保存目录
libs文件夹:第三方类库的保存目录
utils文件夹:子应用的公共函数类库
scripts文件夹:保存项目运营时的脚本文件
2,配置数据库
2.1 创建数据库
在cmd连接上数据库,以root身份进入,然后输入:create database lufei default charset=utf8; 这样就创建了一个名为lufei的数据库
2.2 为当前lufei数据库创建用户,而且设置此用户只能看到这个数据库
create user lufei_user identified by 'lufei';
#创建一个名为lufei_user的用户,密码为lufei
grant all privileges on lufei.* to 'lufei_user'@'%';
#为此用户分配权限,此用户的权限是lufei库
flush privileges;
#刷新权限
2.3 在项目的settings.py文件中配置数据库连接
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql", #表示连接的是mysql数据库
"HOST": "127.0.0.1",
"PORT": 3306, #mysql默认端口号3306
"USER": "lufei_user", #用户名
"PASSWORD": "lufei", #密码
"NAME": "lufei", #连接的是lufei库
}
}
2.4 在项目下的主模块的__init__.py配置
import pymysql
pymysql.install_as_MySQLdb()
3,日志配置
在settings.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(os.path.dirname(BASE_DIR), "logs/lufei.log"),
'maxBytes': 300 * 1024 * 1024,
'backupCount': 10,
'formatter': 'verbose'
},
},
'loggers': {
'django': {
'handlers': ['console', 'file'],
'propagate': True,
},
}
}
4,把rest_framework注入Apps中:
在settings.py文件下的INSTALLED_APPS变量中加入
INSTALLED_APPS = [
'rest_framework',
]
5,异常处理配置
在utils文件夹下新建一个exceptions.py文件
from rest_framework.views import exception_handler
from django.db import DatabaseError
from rest_framework.response import Response
from rest_framework import status
import logging
logger = logging.getLogger('lufei')
def custom_exception_handler(exc, context):
"""
自定义异常处理
:param exc: 异常类
:param context: 抛出异常的上下文
:return: Response响应对象
"""
# 调用drf框架原生的异常处理方法
response = exception_handler(exc, context)
if response is None:
view = context['view']
if isinstance(exc, DatabaseError):
# 数据库异常
logger.error('[%s] %s' % (view, exc))
response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
return response
在settings.py文件下REST_FRAMEWORK变量中添加:
REST_FRAMEWORK = {
# 异常处理
'EXCEPTION_HANDLER': 'lufei.utils.exceptions.custom_exception_handler',
}
四、解决前端vue项目跨域问题
前端vue项目和后端drf项目是运行在不同服务器上的,所以我们在前端页面中用axios发送请求,会遇到同源策略的问题,导致vue前端项目拿不到数据,解决同源策略我们可以瞎用CORS,就是在后端设定可以跨域请求的白名单,然后给这些白名单的响应里加入‘Access-Control-Allow-Origin’,这样浏览器就可以放行了,前端就拿到数据了。
在django里面可以使用插件‘django-cors-headers’帮我们解决跨域问题。
1,为前端和后端设置不同的域名
1.1 修改host文件
Windows系统下位置:c:\windows\system32\driver\etc\host
我们把后端域名改为:api.lufei.cn
前端域名改为:www.lufei.cn
所以我们需要在host文件中加入:
127.0.0.1 api.luffycity.cn
127.0.0.1 www.luffycity.cn
1.2 配置settings.py文件
# 设置哪些客户端可以通过地址访问到后端
ALLOWED_HOSTS = [
'api.lufei.cn',
'www.lufei.cn',
'localhost', # 实际开发的时候不会写上localhost和127.0.0.1的
'127.0.0.1',
]
2,解决跨域问题
2.1 安装插件
pip install django-cors-headers
#记得是在虚拟环境下安装
2.2 setting.py配置
首先在APPS里面注入插件
在变量INSTALLED_APPS添加
INSTALLED_APPS = (
'corsheaders',
)
其次是添加中间件
在MIDDLEWARE变量中添加,切记添加在列表的第一个
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
最后就可以设置放行白名单了
# CORS组的配置信息
CORS_ORIGIN_WHITELIST = (
'127.0.0.1:8080',
'localhost:8080',
'www.lufei.cn:8080'
)
CORS_ALLOW_CREDENTIALS = True # 允许ajax跨域请求时携带cookie
这样设置后,前端页面就可以放心的用axios请求拿取数据了