Django应用上线前的注意事项
单元测试
首先在整个应用上线前,应该有完整的单元测试去测试各模块的功能。通常需在写代码的过程中甚至之前需要写好单元测试,以便高效维护代码的设计结构。我们可以使用Python自带的UnitTest或者Django的TestCase,这里介绍下Django的TestCase。下图为Django TestCase的几个重要的基类:
- SimpleTestCase:继承自python,可以发起HTTP请求,跟页面模板以及URL做交互,但是该基类禁止了数据库的访问。
- TransactionTestCase:继承自该类的测试用例运行时会直接将数据写到数据表,在运行完测试用例之后,会清理掉所有的表数据。用例运行过程中可以通过Transaction的提交、回滚。代码涉及事务可以使用这个基类。
- TestCase:一般情况直接继承该类写单测即可。该类不会实际写入数据表,用例跑完后会直接Rollback,所有的数据操作均不会生效。
- LiveServerTestCase:该类会直接启动整个Django服务,可以测试真实的本地HTTP的地址,每个HTTP服务都可以用这个类测试。可以使用外部工具如Selenium做测试。
from django.test import TestCase
class MyTestCase(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# 具体处理类的代码实现
@classmethod
def tearDownClass(cls):
# 具体处理类的代码实现
super().tearDownClass()
def setUp(self):
pass
def tearDown(self):
pass
def test_something_that_will_pass(self):
self.assertFalse(False)
setUpClass和tearDownClass 分别是在整个类加载的时候去运行setUp做一些准备工作,等到类下的所有TestCase运行完后再运行tearDown做清理。测试用例为test头的文件,会一个个执行。
setUp和tearDown方法是对一个运行的实例,即class运行单次测试前后做的处理。
Django中如何做单元测试
- 目录结构
建议在每个应用下增加testcase的package,在包下放几个测试用例:
job/
/testcase/
__init__.py
test_forms.py
test_views.py
- 测试逻辑
比如Dajngo自带的ORM功能是不需要测试的;自己写的代码需要做单测。
- 执行方法
# 运行项目下面所有 test
$python manage.py test
# 测试指定模块
$python manage.py test jobs.testcase
# 测试单个模块中的文件
$python manage.py test jobs.testcase.test_views
# 指定类
$python manage.py test jobs.testcase.test_views.JobTests
# 测试指定方法
$python manage.py test jobs.testcase.test_views.JobTests.test_detail
发布到生产环境的步骤
url请求进来后先到Nginx 服务器,由Nginx 服务器去做后端的路由转发(proxy_pass)把请求的URL代理到后端,后端处理完动态内容再返回给前端;同时也提供了静态资源服务的功能。
1、配置生产环境配置 (settings):DEBUG & Secret 相关信息
须要调整的关键配置:
- DEBUG:在生产环境中设置为 False(DEBUG = False);避免在 web 页面上显示敏感的调试跟踪和变量信息。
- SECRET_KEY:这个是用作CSRF处理的Token。
- ALLOWED_HOSTS:生产环境必须设置允许访问应用的域名。
- 生成 SECRET KEY。
2、选择 Django App 的托管环境 (IaaS/PaaS,比如阿里云 / AWS/Azure/GAE/Heroku 等等)
密钥的存储和管理:
- 从配置文件中读取,或者从环境变量中读取(明文):
import os
DEBUG = False
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'xxxxxx')
ALLOWED_HOSTS = ["127.0.0.1", "recruit.ihopeit.com", ]
- 从KMS系统中读取配置的密钥:
自己部署的KMS系统
云服务的KMS服务:阿里云/AWS的KMS服务
3、部署前的安全检查
python manage.py check --deploy
4、部署到生产环境:
- 选择静态资源文件的托管环境:可以使用Apache / Nginx / CDN服务器
Django自带collectstatic工具,用来将整个站点需要用到的静态资源(如:CSS/JS/图片等)全部收集起来,放到项目工程的STATIC目录下,该目录可直接通过web服务器(如Nginx)开放出去,或者上传到CDN服务器,让CDN回源到服务器上的这个目录,从而找到静态资源文件。
python manage.py collectstatic --settings=settings.local
STATIC_URL:能够访问到静态文件的 URL 路径
STATIC_ROOT:collectstatic 工具用来保存收集到的项目引用到的任何静态文件的路径
STATICFILES_DIRS:这列出了 Django 的 collectstatic 工具应该搜索静态文件的其他目录
# settings/base.py
STATIC_URL = '/static/'
STATIC_ROOT = 'static'
# settings/local.py
# STATIC_URL = 'http://icdn.ihopeit.com/static' # 使用CDN
STATIC_URL = '/static/'
5、部署 Django 应用容器
同步应用:
- uWSGI: C 实现的 Python Web 容器;Web 服务器 Apache/Nginx 与 django-uwsgi 进程通信来提供动态的内容。
- gunicorn:纯 Python 实现的高性能 Python 应用容器,无外部依赖,简单容易配置; 还没有遇到性能问题的时候,推荐使用 gunicorn。
异步应用:
- Daphne:twisted 实现
- Hypercorn:基于 sans-io hyper,h11,h2,wsproto 实现
- Uvicorn:基于 uvloop and httptools 实现
异步视图代码如下:
async def view(request):
await asyncio.sleep(0.5)
return HttpResponse("Hello,async world ! ")
6、启动应用容器
启动gunicorn:
$ python -m pip install gunicorn
$ export DJANGO_SETTINGS_MODULE=settings.local
$ gunicorn -w 3 -b 127.0.0.1:8000 recruitment.wsgi:application
启动3个worker进程,绑定到本机的8000端口
启动Uvicorn:
$ python -m pip install uvicorn
$ export DJANGO_SETTINGS_MODULE=settings.local
$ uvicorn recruitment.asgi:application --workers 3 --host 127.0.0.1 --port 8000
注意:1、启动应用容器是不提供静态资源服务的。生产环境中将提供静态资源服务的功能放在前端的Web服务器上去的,比如Nginx Tengine或者是Apache上,再对于其它的动态请求做URL路由分发转发到后端的容器服务。
2、在使用异步容器的时候,代码里不能直接使用同步代码,所有的调用都应该是异步的。Django中自带的类是有做兼容处理的,会默认将同步调用转为异步调用,但有些第三方插件未做兼容的话会报错。