Pyinstaller打包Django项目(记录一下踩过的各种坑)

背景
网络应用编程课程设计用Django做了一个火车订票系统(Python3.80+Django3.14+mysql8.0),老师要求打包成exe文件方便检查,踩坑之路由此开始。
正式打包步骤:
(贴一下项目结构)Pyinstaller打包Django项目(记录一下踩过的各种坑)_第1张图片
1、安装pyinstaller

pip install pyinstaller

2、制作.spec文件:进入manage.py文件所在目录下运行

pyi-makespec -D manage.py

运行成功后可在项目所在目录下发现一个spec(规范)文件
Pyinstaller打包Django项目(记录一下踩过的各种坑)_第2张图片
3、开始打包

pyinstaller manage.spec

运行成功后会新增两个build、dist文件夹,我们需要的manage.exe文件就在dist/manage/目录下。
Pyinstaller打包Django项目(记录一下踩过的各种坑)_第3张图片

4、运行exe文件

manage.exe runserver

很开心,通过上面几步出现了我们想要的exe文件,但是麻烦也就此开始。


踩过的坑


1、运行exe文件时报错:RuntimeError: Script runserver does not exist.[7484] Failed to execute script manage
Pyinstaller打包Django项目(记录一下踩过的各种坑)_第4张图片
解决方法:将运行exe文件的命令改为:

manage.exe runserver --noreload

2、按照1的方式去运行exe文件,没有报错,在浏览器输入:http://127.0.0.1:8000/打开网址时报错:TemplateDoesNotExist
Pyinstaller打包Django项目(记录一下踩过的各种坑)_第5张图片
解决方法:上面报错提示找不到我们的template文件,由于pyinstaller打包py文件时并不会打包诸如html、ccs、js、image等静态文件进去(这点很重要!!!)。需要将我们项目的整个templates文件夹复制到与manage.exe同级目录下。

Pyinstaller打包Django项目(记录一下踩过的各种坑)_第6张图片
重新运行exe文件,在浏览器输入网址,发现现在可以正常使用了。

但是!!!踩坑之路还没结束,在本地可以运行的exe文件,换到其他电脑上运行时是这样的:

Pyinstaller打包Django项目(记录一下踩过的各种坑)_第7张图片
页面上的图片全部缺失了!!!打开开发者工具一看,发现页面请求图片失败导致图片加载不出来。

Pyinstaller打包Django项目(记录一下踩过的各种坑)_第8张图片
于是,最麻烦的坑来了。这个花费的时间最长,因此下面会用较长篇幅去介绍解决方法。
3、加载图片失败

首先需要了解一下django的开发者模式,在django项目的settings文件下有这样一句代码:

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

一般我们运行django项目默认是打开开发者模式的,这个时候django便会自动帮我们对静态文件进行路由;但是当我们设置DEBUG = False后,相当于是生产环境,此时静态文件就会出现加载失败的情况。
再来看看settings文件下的STATIC_URL、STATIC_ROOT、STATICFILES_DIRS三个变量。

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')     # 新增
STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'static'),
]

网上有很多介绍的文章,这里简单说一下。我们一般会把某个app中的js、css、image等静态文件放在该app目录下的static文件夹中,而多个app共享的静态文件放在项目所在目录下的static文件夹中。查找静态文件时,会先去app下的static文件夹查找,如果找不到,则去STATICFILES_DIRS 中指出的路径去查找。
而我们的主角是STATIC_ROOT,STATIC_ROOT 是在部署的时候才发挥作用,它聚合了各个static文件夹下的所有静态文件,以供部署后查找静态文件。当执行下面这行代码时,django会把所有的static文件都复制到STATIC_ROOT文件夹下。

python manage.py collectstatic

所以我们应该在打包django前设置好STATIC_ROOT ,可参考官方文档。
详细解决步骤:

1.在settings文件中设置STATIC_ROOT:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')     # 新增
STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'static'),
]

2.执行下面命令把所有的static文件都复制到STATIC_ROOT文件夹下:

python manage.py collectstatic

3.在项目的urls文件下新增:

from django.conf.urls import static
urlpatterns += static.static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

4.最后需要将STATIC_ROOT中的静态文件打包到.exe中,配置前面提到的manage.spec文件,在datas(datas用于添加额外的文件)中加入元组:

(r'D:\PycharmProjects\o12307\static_root',r'.\static_root')

Pyinstaller打包Django项目(记录一下踩过的各种坑)_第9张图片
第一部分代表static_root文件夹的绝对路径,第二部分则表示相对路径。考虑到第二个坑中需要手动复制templates文件,在这里我们也把templates打包进去,免去手动复制的麻烦。最后的datas是:

datas=[(r'D:\PycharmProjects\o12307\static_root',r'.\static_root'),(r'D:\PycharmProjects\o12307\templates', r'.\templates')],

5.再次执行打包命令:

pyinstaller manage.spec

成功运行在其他机器上,完美解决!!!

你可能感兴趣的:(笔记,python,django,pyinstaller,web开发)