Python从入门到放弃:Django+uwsgi+nginx的部署

    技术2022-07-10  148

    Django+uwsgi+nginx的部署

    欢迎使用Django+uwsgi+nginxDjangowindows安装python创建DJango项目连接数据库 uWSGI在Linux上安装python3安装uWSGI 创建python的虚拟环境使用uWSGI启动Djangonginx

    欢迎使用Django+uwsgi+nginx

    最近被要求使用python写接口,这让写了三年java接口的我又要从一个小白开始写起。搞了两天,翻阅了无数的博客,终于搞了一个大概。这次从初始化创建Django开始,到正式访问结束。大家凑乎看看吧。。。

    Django

    Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。 使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务 Django 本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。 ----摘自菜鸟教程

    本次开发使用的开发工具为Pycharm,一款出自于JetBrains的优秀的python开发工具。主要是IDEA开发JAVA的时间长了,对这个布局已经很熟悉了,懒得换而已。

    windows安装python

    我使用的是windows电脑,具体安装方法为:

    进入python的官方网站:点我啊,标题栏有个downloads,选择你的系统,找到对应的位数,点击之后就可以下载了(选择那个executable那个的)。 下载完毕后,有一个.exe的文件,打开它,红框内的东西记住选了,完了一路下一步就可以了。 安装好之后,使用键盘的WIN+R调出运行,输入cmd,键入python -V。如果出现以下图片,证明你的python已经安装好了。

    创建DJango项目

    打开Pycharm,左上角选择file,new project,左边选择Django,右边输入你喜欢的名字,create! 这就是Django的一个初始化的格式,我们需要新建一个module 在下面的Terminal中键入django-admin.py startapp appTest,就会新增一个app模块 views.py相当于MVC项目中的Controller的作用,用来接收请求,而@RequestMaping相关的映射配置在urls.py中 5.右上角启动之后,点击控制台的连接,在地址后面输入hello就可以看到页面啦

    连接数据库

    数据库相关的配置是配置在setting.py中的,django默认使用的数据库为sqlite3,你可以根据自己的需求配置不同的数据库

    oracle:

    'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'ip:port/databaseName', 'USER': 'userName', 'PASSWORD': 'password', },

    mysql:

    'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "databaseName", 'USER':'userName', 'PASSWORD': 'password', 'HOST': 'ip', 'PORT': 'port' },

    注:在连接oracle的时候,需要下载cx_oracle,并且这玩意还必须根据你的数据库版本及位数,python版本和位数来下载,稍微有一点不一样就会报错 oracle报错:

    django.core.exceptions.ImproperlyConfigured: Error loading cx_Oracle module: No module named 'cx_Oracle'

    这个错误的原因是你使用了连接oracle但是却没有拿到oracle的驱动之类的,因此需要下载cx_oracle,进去之后找到符合你python位数和数据库版本的cx_oracle 安装一下就好了(我是直接执行pip install cx-Oracle) 进入oracle网站,选择符合你系统位数的连接,点进去后寻找你数据库的版本,下载完成后,解压,将文件中的oci.dll、oraocci11.dll、oraociei11.dll这三个文件拷贝到项目中,路径是项目名\venv\Lib\site-packages\

    mysql: Traceback (most recent call last) File CUsersLenovoAppDataLocalProgramsPythonPython38libthreading.py, line 932, in _bootstrap_inner self.run() File CUsersLenovoAppDataLocalProgramsPythonPython38libthreading.py, line 870, in run self._target(self._args, self._kwargs) File EDjangoTestvenvlibsite-packagesdjangoutilsautoreload.py, line 53, in wrapper fn(args, kwargs) File EDjangoTestvenvlibsite-packagesdjangocoremanagementcommandsrunserver.py, line 109, in inner_run autoreload.raise_last_exception() File EDjangoTestvenvlibsite-packagesdjangoutilsautoreload.py, line 76, in raise_last_exception raise _exception[1] File EDjangoTestvenvlibsite-packagesdjangocoremanagement__init__.py, line 357, in execute autoreload.check_errors(django.setup)() File EDjangoTestvenvlibsite-packagesdjangoutilsautoreload.py, line 53, in wrapper fn(args, kwargs) File EDjangoTestvenvlibsite-packagesdjango__init__.py, line 24, in setup apps.populate(settings.INSTALLED_APPS) File EDjangoTestvenvlibsite-packagesdjangoappsregistry.py, line 114, in populate app_config.import_models() File EDjangoTestvenvlibsite-packagesdjangoappsconfig.py, line 211, in import_models self.models_module = import_module(models_module_name) File CUsersLenovoAppDataLocalProgramsPythonPython38libimportlib__init__.py, line 127, in import_module return _bootstrap._gcd_import(name[level], package, level) File frozen importlib._bootstrap, line 1014, in _gcd_import File frozen importlib._bootstrap, line 991, in _find_and_load File frozen importlib._bootstrap, line 975, in _find_and_load_unlocked File frozen importlib._bootstrap, line 671, in _load_unlocked File frozen importlib._bootstrap_external, line 783, in exec_module File frozen importlib._bootstrap, line 219, in _call_with_frames_removed File EDjangoTestvenvlibsite-packagesdjangocontribauthmodels.py, line 2, in module from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager File EDjangoTestvenvlibsite-packagesdjangocontribauthbase_user.py, line 47, in module class AbstractBaseUser(models.Model) File EDjangoTestvenvlibsite-packagesdjangodbmodelsbase.py, line 121, in __new__ new_class.add_to_class('_meta', Options(meta, app_label)) File EDjangoTestvenvlibsite-packagesdjangodbmodelsbase.py, line 325, in add_to_class value.contribute_to_class(cls, name) File EDjangoTestvenvlibsite-packagesdjangodbmodelsoptions.py, line 208, in contribute_to_class self.db_table = truncate_name(self.db_table, connection.ops.max_name_length()) File EDjangoTestvenvlibsite-packagesdjangodb__init__.py, line 28, in __getattr__ return getattr(connections[DEFAULT_DB_ALIAS], item) File EDjangoTestvenvlibsite-packagesdjangodbutils.py, line 207, in __getitem__ backend = load_backend(db['ENGINE']) File EDjangoTestvenvlibsite-packagesdjangodbutils.py, line 111, in load_backend return import_module('%s.base' % backend_name) File CUsersLenovoAppDataLocalProgramsPythonPython38libimportlib__init__.py, line 127, in import_module return _bootstrap._gcd_import(name[level], package, level) File EDjangoTestvenvlibsite-packagesdjangodbbackendsmysqlbase.py, line 18, in module raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured Error loading MySQLdb module. Did you install mysqlclient

    解决办法:简单明了,看到最后一句了没?Did you install mysqlclient?来自灵魂深处的提问,所以解决办法就是: pip install mysqlclient

    uWSGI

    uWSGI 是一个快速的、纯C语言开发的、自维护的、对开发者友好的 WSGI 服务器,旨在提供专业的 Python web应用发布和开发。可使用 C/C++/Objective-C 来为 uWSGI 编写插件。 – 摘自开源中国

    在Linux上安装python3

    参见linux安装python3的方法 附链接一只:wget https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz

    安装uWSGI

    按照第一步装好python了之后,我们可以使用pip3命令去下载关于python的模块了,我们使用pip3 install uwsgi 安装完成后,会有一行提示 WARNING: You are using pip version 19.2.3, however version 20.1.1 is available. You should consider upgrading via the 'pip install --upgrade pip' command.

    看着应该是要执行的,就执行一下吧pip3 install --upgrade pip 为uwsgi建立软连接 ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi

    安装好了之后,为了测试我们的uWSGI有没有安装成功,我们可以建立一个测试类来测试一下。 进入一个你喜欢的目录(我是建了一个新的用户进行测试),写一个python脚本:firstpy.py def application ( env,start_response ): start_response ('200 OK',[('Content-Type','text / html' )]) return [ b"Hello World"]

    保存之后,执行命令uwsgi --http :8080 --wsgi-file firstpy.py 访问你的服务器地址+端口号,例如我的是192.168.1.101:8080。看到以下页面即视为安装成功

    创建python的虚拟环境

    安装virtualenvwrapper,登录服务器(root或者你自己的都行)使用pip3安装virtualenvwrapper pip3 install virtualenvwrapper把下面两行代码添加到 ~/.bashrc文件中 打开文件 vim ~/.bashrc 写入以下两行代码 export WORKON_HOME=~/fakeEnv #设置virtualenv的统一管理目录 export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--no-site-packages' #添加virtualenvwrapper的参数,生成干净隔绝的环境 export VIRTUALENVWRAPPER_PYTHON=/opt/python347/bin/python3 #指定python解释器 source /opt/python34/bin/virtualenvwrapper.sh #执行virtualenvwrapper安装脚本

    读取文件,使得生效,此时已经可以使用virtalenvwrapper source ~/.bashrc

    创建一个虚拟环境: mkvirtualenv django

    这会在 ~/fakeEnv 中创建 django文件夹。此时,你的虚拟环境的目录就是django

    在虚拟环境上工作:激活虚拟环境django

    workon django

    手动停止虚拟环境

    deactivate

    删除虚拟环境,需要先退出虚拟环境

    rmvirtualenv django

    进入虚拟环境

    source ~/fakeEnv/django/bin/activate

    这时你能在你的用户名前看到(django),这就说明你已经进入虚拟环境了

    在Pycharm上开发完成后,你可以使用命令pip freeze > requirements.txt将你在开发时导入的依赖库导出,并且在虚拟环境中执行pip install -r requirements.txt安装项目依赖。关于代码,可以选择直接从git下拉,也可以本地直接打包,然后放在指定目录解压出来就行了

    注意:部署时有关数据库的坑: 在部署成功之后,我进入了我的项目,想使用命令python3 manage.py runserver来启动项目,结果却遇到了一个奇怪的错误

    (django) [python@localhost pythonDjango]$ python3 manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). Exception in thread django-main-thread: Traceback (most recent call last): File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 197, in connect self.connection = self.get_new_connection(conn_params) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/oracle/base.py", line 228, in get_new_connection return Database.connect( cx_Oracle.DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html for help The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/python3/lib/python3.8/threading.py", line 932, in _bootstrap_inner self.run() File "/usr/local/python3/lib/python3.8/threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/autoreload.py", line 53, in wrapper fn(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 120, in inner_run self.check_migrations() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/core/management/base.py", line 458, in check_migrations executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS]) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/migrations/executor.py", line 18, in __init__ self.loader = MigrationLoader(self.connection) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/migrations/loader.py", line 49, in __init__ self.build_graph() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/migrations/loader.py", line 212, in build_graph self.applied_migrations = recorder.applied_migrations() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/migrations/recorder.py", line 76, in applied_migrations if self.has_table(): File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/migrations/recorder.py", line 56, in has_table return self.Migration._meta.db_table in self.connection.introspection.table_names(self.connection.cursor()) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 260, in cursor return self._cursor() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 236, in _cursor self.ensure_connection() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/base/base.py", line 197, in connect self.connection = self.get_new_connection(conn_params) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/home/python/fakeEnv/django/lib/python3.8/site-packages/django/db/backends/oracle/base.py", line 228, in get_new_connection return Database.connect( django.db.utils.DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html for help

    一开始百度,他们都说是因为python的位数或者oracle的位数与cx_oracle的位数不一致导致的,但是我反复确认,的确都是64位的。正当我快把头发都拔光的时候,突然想起来我在开发的时候从oracle官网下载了一个包,把oci.dll等文件拷贝进了我的开发环境的虚拟环境中,这时我在luinx中重新创建虚拟环境,那我的那些包是不是需要重新拷贝进去呢?

    通过那些.py文件我确定了我的虚拟环境的地址,接下来我打开了oracle的帮助网站,找到了Install Oracle Client这一段话

    Install Oracle Client Using cx_Oracle requires Oracle Client libraries to be installed. These provide the necessary network connectivity allowing cx_Oracle to access an Oracle Database instance.

    If your database is on a remote computer, then download the free Oracle Instant Client “Basic” or “Basic Light” package for your operating system architecture. Use the RPM or ZIP packages, based on your preferences.

    Download an Oracle 19, 18, 12, or 11.2 “Basic” or “Basic Light” zip file: 64-bit or 32-bit, matching your Python architecture.

    The latest version is recommended. Oracle Instant Client 19 will connect to Oracle Database 11.2 or later.

    Unzip the package into a single directory that is accessible to your application. For example:

    mkdir -p /opt/oracle cd /opt/oracle unzip instantclient-basic-linux.x64-19.6.0.0.0dbru.zip

    Install the libaio package with sudo or as the root user. For example:

    sudo yum install libaio

    On some Linux distributions this package is called libaio1 instead.

    On recent Linux versions, such as Oracle Linux 8, you may also need to install the libnsl package.

    这个步骤就相当于在windows下把oci.dll等文件放到venv下的操作,然后再次进入虚拟环境,执行python3 manage.py runserver,看到了熟悉的成功页面,顿时出了一身冷汗

    使用uWSGI启动Django

    首先需要在与项目同名的目录下创建uwsgi.ini的文件,具体内容如下: [uwsgi] chdir = /home/python/server/pythonDjango #你的项目目录 home = /home/python/fakeEnv/django # 如果有虚拟环境,则需要指定虚拟环境目录; 没有则注释掉 module = pythonDjango.wsgi # 指向自己Django项目目录下mysite目录下的wsgi文件 master = True processes = 4 # 使用进程数 harakiri = 60 # 最大超时时间 max-requests = 5000 # 最大请求数,到了后就会自动重启 socket = 127.0.0.1:8080 # socket连接地址和端口,和之前nginx配置一致 pidfile = /home/python/server/pythonDjango/pythonDjango/pythonDjango.pid #在失去权限前,将pid写到指定的pidfile文件中 daemonize = /home/python/logs/pythonDjango/pythonDjango.log # 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器 # chmod-socket = 664 # 如果没有权限访问uWSGI的socket,这里可以设置权限 vacuum = True # 服务退出或重启,自动删除pid和socket文件 保存后使用命令uwsgi --ini uwsgi.ini即可启动项目重启:uwsgi --reload pythonDjango.pid,停止:uwsgi --stop pythonDjango.pid

    nginx

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。 –摘自百度百科

    这一部分没啥好说的,直接贴nginx.conf: http{ upstream django { # 注意这里的server要和uwsgi.ini配置文件中的socket保持一致 server 127.0.0.1:8080; # for a web port socket } server { listen 8881; server_name localhost; # 这里填自己的域名或者服务器的ip(决定你今后访问网站的方式) charset utf-8; root /usr/share/nginx/html; location / { root /home/python/server/pythonDjango/appTest; # 这是Django App的路径 uwsgi_pass django; include uwsgi_params; # the uwsgi_params file you installed } } } 完成之后,重启nginx: ./nginx -s reload
    Processed: 0.042, SQL: 9