前面的文章把博客的基本功能开发已经完成,具体的细节还需要调整的地方可以根据需求进行调整。本篇作为本系列最后一篇文章,主要讲一下如何把项目部署到外网,以便于大家都能访问到。
这里部署基于 pythonanywhere 网站:
https://www.pythonanywhere.com/
这里需要事先在网站注册一个账号。pythonanywhere 支持部署一个免费的项目,如果部署多个则需要付费使用。

注册完成后,定位到 web 分类下。接下里则要开始部署工作:
通过 Add a new web app -> Manual configuration(自定义配置) -> python3.7(根据自己开发环境的配置) 创建一个空的新项目。

根据生成的域名,需要去配置相关内容。
拿到这里的域名 huhaiqiang005.pythonanywhere.com 到对应项目中 setting.py 中配置 ALLOWED_HOSTS:
DEBUG = False
ALLOWED_HOSTS = ['huhaiqiang005.pythonanywhere.com']
配置完成后,将项目打包成 zip 文件并通过 pythonanywhere Files 下进行上传工作:

项目上传完成后,通过 Open Bash Console here 打开控制台将对上传的项目进行解压等操作。
04:34 ~ $ pwd
/home/huhaiqiang005
04:36 ~ $ ls
2_blog.zip README.txt
04:37 ~ $ unzip 2_blog.zip
Archive: 2_blog.zip
creating: 2_blog/
creating: 2_blog/.idea/
inflating: 2_blog/.idea/blog.iml
creating: 2_blog/.idea/inspectionProfiles/
creating: 2_blog/.idea/libraries/
inflating: 2_blog/.idea/libraries/R_User_Library.xml
inflating: 2_blog/.idea/misc.xml
inflating: 2_blog/.idea/modules.xml
inflating: 2_blog/.idea/workspace.xml
creating: 2_blog/blog/
inflating: 2_blog/blog/settings.py
inflating: 2_blog/blog/settings.pyc
inflating: 2_blog/blog/urls.py
inflating: 2_blog/blog/urls.pyc
inflating: 2_blog/blog/wsgi.py
inflating: 2_blog/blog/wsgi.pyc
extracting: 2_blog/blog/__init__.py
inflating: 2_blog/blog/__init__.pyc
creating: 2_blog/blog/__pycache__/
inflating: 2_blog/blog/__pycache__/settings.cpython-37.pyc
inflating: 2_blog/blog/__pycache__/urls.cpython-37.pyc
inflating: 2_blog/blog/__pycache__/wsgi.cpython-37.pyc
inflating: 2_blog/blog/__pycache__/__init__.cpython-37.pyc
inflating: 2_blog/db.sqlite3
inflating: 2_blog/manage.py
creating: 2_blog/post/
inflating: 2_blog/post/admin.py
inflating: 2_blog/post/admin.pyc
inflating: 2_blog/post/apps.py
creating: 2_blog/post/migrations/
inflating: 2_blog/post/migrations/0001_initial.py
extracting: 2_blog/post/migrations/__init__.py
creating: 2_blog/post/migrations/__pycache__/
inflating: 2_blog/post/migrations/__pycache__/0001_initial.cpython-37.pyc
inflating: 2_blog/post/migrations/__pycache__/__init__.cpython-37.pyc
inflating: 2_blog/post/models.py
inflating: 2_blog/post/models.pyc
inflating: 2_blog/post/mycontextprocessor.py
inflating: 2_blog/post/search_indexes.py
creating: 2_blog/post/templates/
inflating: 2_blog/post/templates/article.html
inflating: 2_blog/post/templates/index.html
inflating: 2_blog/post/templates/post_detail.html
creating: 2_blog/post/templatetags/
inflating: 2_blog/post/templatetags/myfilter.py
extracting: 2_blog/post/templatetags/__init__.py
creating: 2_blog/post/templatetags/__pycache__/
inflating: 2_blog/post/templatetags/__pycache__/myfilter.cpython-37.pyc
inflating: 2_blog/post/templatetags/__pycache__/__init__.cpython-37.pyc
inflating: 2_blog/post/tests.py
inflating: 2_blog/post/tokenizer.py
inflating: 2_blog/post/urls.py
inflating: 2_blog/post/urls.pyc
inflating: 2_blog/post/views.py
inflating: 2_blog/post/views.pyc
inflating: 2_blog/post/whoosh_cn_backend.py
inflating: 2_blog/post/__init__.py
inflating: 2_blog/post/__init__.pyc
creating: 2_blog/post/__pycache__/
inflating: 2_blog/post/__pycache__/admin.cpython-37.pyc
inflating: 2_blog/post/__pycache__/models.cpython-37.pyc
inflating: 2_blog/post/__pycache__/mycontextprocessor.cpython-37.pyc
inflating: 2_blog/post/__pycache__/search_indexes.cpython-37.pyc
inflating: 2_blog/post/__pycache__/tokenizer.cpython-37.pyc
inflating: 2_blog/post/__pycache__/urls.cpython-37.pyc
inflating: 2_blog/post/__pycache__/views.cpython-37.pyc
inflating: 2_blog/post/__pycache__/whoosh_cn_backend.cpython-37.pyc
inflating: 2_blog/post/__pycache__/__init__.cpython-37.pyc
creating: 2_blog/static/
creating: 2_blog/static/css/
inflating: 2_blog/static/css/style.css
creating: 2_blog/templates/
inflating: 2_blog/templates/base.html
inflating: 2_blog/templates/footer.html
inflating: 2_blog/templates/header.html
inflating: 2_blog/templates/right.html
creating: 2_blog/templates/search/
creating: 2_blog/templates/search/indexes/
creating: 2_blog/templates/search/indexes/post/
inflating: 2_blog/templates/search/indexes/post/post_text.txt
inflating: 2_blog/templates/search/search.html
creating: 2_blog/whoosh_index/
inflating: 2_blog/whoosh_index/MAIN_3scwr53g0w24zzop.seg
extracting: 2_blog/whoosh_index/MAIN_WRITELOCK
inflating: 2_blog/whoosh_index/_MAIN_1.toc
04:37 ~ $ ls
2_blog 2_blog.zip README.txt
04:37 ~ $ rm -r 2_blog.zip
04:37 ~ $ ls
2_blog README.txt
05:38 ~ $ cd 2_blog
05:39 ~/2_blog $ pwd
/home/huhaiqiang005/2_blog
05:39 ~/2_blog $
获取到项目路径后进行 web 配置:

配置完成项目地址后,再对 WSGI 配置文件进行修改。
注释 Hello World 案列,同时打开 django 的配置信息:
# HELLO_WORLD = """<html>
# <head>
# <title>PythonAnywhere hosted web application</title>
# </head>
# <body>
# <h1>Hello, World!</h1>
# <p>
# This is the default welcome page for a
# <a href="https://www.pythonanywhere.com/">PythonAnywhere</a>
# hosted web application.
# </p>
# <p>
# Find out more about how to configure your own web application
# by visiting the <a href="https://www.pythonanywhere.com/web_app_setup/">web app setup</a> page
# </p>
# </body>
# </html>"""
# def application(environ, start_response):
# if environ.get('PATH_INFO') == '/':
# status = '200 OK'
# content = HELLO_WORLD
# else:
# status = '404 NOT FOUND'
# content = 'Page not found.'
# response_headers = [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]
# start_response(status, response_headers)
# yield content.encode('utf8')
......
# +++++++++++ DJANGO +++++++++++
# To use your own django app use code like this:
import os
import sys
#
## assuming your django settings file is at '/home/huhaiqiang005/mysite/mysite/settings.py'
## and your manage.py is is at '/home/huhaiqiang005/mysite/manage.py'
path = '/home/huhaiqiang005/2_blog'
if path not in sys.path:
sys.path.append(path)
#
os.environ['DJANGO_SETTINGS_MODULE'] = 'blog.settings'
#
## then:
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
配置完成项目相关路径以及文件的配置,接下还需要配置一个虚拟环境,项目实际是在虚拟环境上运行。
欢迎关注公众号 【python面面观】,在聊天对话框回复「博客」获取源码地址以及其他 python 相关知识。
虚拟环境
进入到控制台:
virtualenv blogenv --python=python3.7 创建虚拟环境
05:39 ~/2_blog $ cd ~
05:48 ~ $ virtualenv blogenv --python=python3.7
Running virtualenv with interpreter /usr/bin/python3.7
Already using interpreter /usr/bin/python3.7
Using base prefix '/usr'
New python executable in /home/huhaiqiang005/blogenv/bin/python3.7
Also creating executable in /home/huhaiqiang005/blogenv/bin/python
Installing se
source activate 激活虚拟环境
05:50 ~ $ ls
2_blog README.txt blogenv
05:50 ~ $ cd blogenv
05:51 ~/blogenv $ ls
bin include lib
05:51 ~/blogenv $ cd bin
05:51 ~/blogenv/bin $ source activate
(blogenv) 05:51 ~/blogenv/bin $ cd ~
(blogenv) 05:51 ~ $ cd blogenv
(blogenv) 05:52 ~/blogenv $ pwd
/home/huhaiqiang005/blogenv
(blogenv) 05:52 ~/blogenv $
激活虚拟环境后,需要把对应的虚拟环境地址在 pythonanywhere 进行配置:

配置完成虚拟完成,同时需要安装项目中使用到的相关工具。
(blogenv) 05:57 ~/blogenv $ pip list
Package Version
---------- -------
pip 20.2.2
setuptools 49.6.0
wheel 0.35.1
(blogenv) 05:58 ~/blogenv $ cd lib/
(blogenv) 05:58 ~/blogenv/lib $ ls
python3.7
(blogenv) 05:58 ~/blogenv/lib $ cd python3.7
(blogenv) 05:58 ~/blogenv/lib/python3.7 $ ls
LICENSE.txt _weakrefset.py config-3.7m-x86_64-linux-gnu fnmatch.py imp.py locale.py posixpath.py site-packages struct.py warnings.py
__future__.py abc.py copy.py functools.py importlib no-global-site-packages.txt random.py site.py tarfile.py weakref.py
__pycache__ base64.py copyreg.py genericpath.py io.py ntpath.py re.py sre_compile.py tempfile.py
_bootlocale.py bisect.py distutils hashlib.py keyword.py operator.py reprlib.py sre_constants.py token.py
_collections_abc.py codecs.py encodings heapq.py lib-dynload orig-prefix.txt rlcompleter.py sre_parse.py tokenize.py
_dummy_thread.py collections enum.py hmac.py linecache.py os.py shutil.py stat.py types.py
(blogenv) 05:58 ~/blogenv/lib/python3.7 $ cd site-packages
(blogenv) 05:59 ~/blogenv/lib/python3.7/site-packages $ ls
__pycache__ _distutils_hack distutils-precedence.pth easy_install.py pip pip-20.2.2.dist-info pkg_resources setuptools setuptools-49.6.0.dist-info wheel wheel-0.35.1.dist-info
(blogenv) 05:59 ~/blogenv/lib/python3.7/site-packages $ cd ~
(blogenv) 05:59 ~ $ pip install Django==2.1
Looking in links: /usr/share/pip-wheels
Collecting Django==2.1
Downloading Django-2.1-py3-none-any.whl (7.3 MB)
|████████████████████████████████| 7.3 MB 11.3 MB/s
Collecting pytz
Downloading pytz-2020.1-py2.py3-none-any.whl (510 kB)
|████████████████████████████████| 510 kB 743 kB/s
Installing collected packages: pytz, Django
Successfully installed Django-2.1 pytz-2020.1
(blogenv) 06:03 ~ $ pip install django-ckeditor
Looking in links: /usr/share/pip-wheels
Collecting django-ckeditor
Downloading django_ckeditor-5.9.0-py2.py3-none-any.whl (2.4 MB)
|████████████████████████████████| 2.4 MB 11.3 MB/s
Processing /usr/share/pip-wheels/django_js_asset-1.2.2-py2.py3-none-any.whl
Installing collected packages: django-js-asset, django-ckeditor
Successfully installed django-ckeditor-5.9.0 django-js-asset-1.2.2
(blogenv) 06:04 ~ $ pip install django-haystack
Looking in links: /usr/share/pip-wheels
Collecting django-haystack
Downloading django-haystack-2.8.1.tar.gz (1.6 MB)
|████████████████████████████████| 1.6 MB 8.2 MB/s
Requirement already satisfied: Django>=1.11 in ./blogenv/lib/python3.7/site-packages (from django-haystack) (2.1)
Requirement already satisfied: pytz in ./blogenv/lib/python3.7/site-packages (from Django>=1.11->django-haystack) (2020.1)
Building wheels for collected packages: django-haystack
Building wheel for django-haystack (setup.py) ... done
Created wheel for django-haystack: filename=django_haystack-2.8.1-py3-none-any.whl size=131001 sha256=8c2d5bee18af117a913744dd0d10c6c215b4361727ba629c8f3efd7ea8067726
Stored in directory: /home/huhaiqiang005/.cache/pip/wheels/3e/44/38/11034123a4528eb6e7fc6684e0ba4165a572761101da7c5386
Successfully built django-haystack
Installing collected packages: django-haystack
Successfully installed django-haystack-2.8.1
(blogenv) 06:06 ~ $ pip install whoosh
Looking in links: /usr/share/pip-wheels
Processing /usr/share/pip-wheels/Whoosh-2.7.4-py2.py3-none-any.whl
Installing collected packages: whoosh
Successfully installed whoosh-2.7.4
(blogenv) 06:07 ~ $ pip install jieba
Looking in links: /usr/share/pip-wheels
Collecting jieba
Downloading jieba-0.42.1.tar.gz (19.2 MB)
|████████████████████████████████| 19.2 MB 49 kB/s
Building wheels for collected packages: jieba
Building wheel for jieba (setup.py) ... done
Created wheel for jieba: filename=jieba-0.42.1-py3-none-any.whl size=19314478 sha256=66a679a297f3ed991b0ac9e46ff7f2a86d17535f51b81810831ffcc87d7e425f
Stored in directory: /home/huhaiqiang005/.cache/pip/wheels/24/aa/17/5bc7c72e9a37990a9620cc3aad0acad1564dcff6dbc2359de3
Successfully built jieba
Installing collected packages: jieba
Successfully installed jieba-0.42.1
(blogenv) 06:07 ~ $ pip install markdown
Looking in links: /usr/share/pip-wheels
Collecting markdown
Downloading Markdown-3.2.2-py3-none-any.whl (88 kB)
|████████████████████████████████| 88 kB 1.8 MB/s
Collecting importlib-metadata; python_version < "3.8"
Downloading importlib_metadata-1.7.0-py2.py3-none-any.whl (31 kB)
Collecting zipp>=0.5
Downloading zipp-3.1.0-py3-none-any.whl (4.9 kB)
Installing collected packages: zipp, importlib-metadata, markdown
Successfully installed importlib-metadata-1.7.0 markdown-3.2.2 zipp-3.1.0
(blogenv) 06:07 ~ $ pip install Pillow
Looking in links: /usr/share/pip-wheels
Collecting Pillow
Downloading Pillow-7.2.0-cp37-cp37m-manylinux1_x86_64.whl (2.2 MB)
|████████████████████████████████| 2.2 MB 801 kB/s
Installing collected packages: Pillow
Successfully installed Pillow-7.2.0
(blogenv) 06:10 ~ $ pip install mysql-connector
Looking in links: /usr/share/pip-wheels
Collecting mysql-connector
Downloading mysql-connector-2.2.9.tar.gz (11.9 MB)
|████████████████████████████████| 11.9 MB 8.7 MB/s
Building wheels for collected packages: mysql-connector
Building wheel for mysql-connector (setup.py) ... done
Created wheel for mysql-connector: filename=mysql_connector-2.2.9-cp37-cp37m-linux_x86_64.whl size=247950 sha256=8a4ee196aa1e0775cb3266761af418a8f25a9f7241aa137354933b95d61b945d
Stored in directory: /home/huhaiqiang005/.cache/pip/wheels/42/2f/c3/692fc7fc1f0d8c06b9175d94f0fc30f4f92348f5df5af1b8b7
Successfully built mysql-connector
Installing collected packages: mysql-connector
Successfully installed mysql-connector-2.2.9
配置完成虚拟环境以及相关工具的安装,继续配置相关静态文件。

上述静态文件配置分别对应 blog项目资源、上传文件资源、后台站点资源、ckeditor 资源对应的配置。
以上分别配置完成代码、环境、资源文件,接下来还有数据库进行配置:
切换到 Database 的配置页面:

设置完成 mysql 密码之后即可生成对应远程 mysql 的相关信息。

对应需要在控制台操作 settings.py 文件的配置,并进行保存:
(blogenv) 08:19 ~/2_blog/blog $ ls
__init__.py __init__.pyc __pycache__ settings.py settings.pyc urls.py urls.pyc wsgi.py wsgi.pyc
(blogenv) 08:19 ~/2_blog/blog $ vi settings.py

配置完成后,在远程重新去生成数据库的迁移文件。
(blogenv) 08:52 ~/2_blog $ python manage.py makemigrations
No changes detected
(blogenv) 08:55 ~/2_blog $ python manage.py migrate
System check identified some issues:
WARNINGS:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
HINT: MySQL's Strict Mode fixes many data integrity problems in MySQL, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https
://docs.djangoproject.com/en/2.1/ref/databases/#mysql-sql-mode
Operations to perform:
Apply all migrations: admin, auth, contenttypes, post, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying post.0001_initial... OK
Applying sessions.0001_initial... OK
数据库相关配置完成之后,去运行项目进行远程方位看一看实际效果:

点击上图按钮运行项目,然后访问 huhaiqiang005.pythonanywhere.com 查看展示效果:

可以正常访问页面,但是现在没有数据,接下来继续创建后台管理员,增加一些数据上去;
(blogenv) 08:57 ~/2_blog $ python manage.py createsuperuser
......
通过后台添加完成数据后,再次运行项目,查看博客页面展示效果:

到这里,整个项目的部署工作就已经完成了,这里对项目的部署流程做一个总结:
- 修改 settings.py
- 拷贝项目到桌面并且添加 zip 压缩包
- 将 blog.zip 文件上传至 pythonanywhere.com[files] 目录中
- 打开 bash 窗口 解压 blog.zip 文件
- 创建虚拟环境 blogenv
- 激活虚拟环境
- 在虚拟环境安装各种模块
- 在 pythonanywhere.com[web] 目录中配置路径
- 配置数据库信息
10.运行项目
本系列的博客项目到这里也已经全部更新完成,如有相关疑问可回顾以往文章或者对应查看源码进行查看分析。
网友评论