简介

首先我们说下 Python 环境管理 (pyenv 和 virtualenv)
pyenv 是一个开源的 Python 版本管理工具,可以轻松地给系统安装任意 Python 版本,想玩哪个版本,瞬间就可以切换。有了 pyenv,我们不需要再为系统多版本 Python 共存问题而发愁,也不用为手动编译安装其他 Python 版本而浪费时间,只需要执行一条简单的命令就可以切换并使用任何其他版本,该工具真正地做到了开箱即用,简单实用。
virtualenv 是一个用来创建完全隔离的 Python 虚拟环境的工具,可以为每个项目工程创建一套独立的 Python 环境,从而可以解决不同工程对 Python 包,或者版本的依赖问题。假如有 A 和 B 两个工程,A 工程代码要跑起来需要 requests 1.18.4,而 B 工程跑起来需要 requests 2.18.4,这样在一个系统中就无法满足两个工程同时运行问题了。最好的解决办法是用 virtualenv 给每个工程创建一个完全隔离的 Python 虚拟环境,给每个虚拟环境安装相应版本的包,让程序使用对应的虚拟环境运行即可。这样既不影响系统 Python 环境,也能保证任何版本的 Python 程序可以在同一系统中运行。

最佳实践:使用 pyenv 安装任何版本的 Python,然后用 virtualenv 创建虚拟环境时指定需要的 Python 版本路径,这样就可以创建任何版本的虚拟环境,这样的实践真是极好的!


文章目录

  • 前言
  • 一 、项目与环境配置
  • 1.配置(pyenv 和 virtualenv)虚拟环境
  • 2.创建指定py版本虚拟环境
  • 二、Uwsgi配置步骤
  • 1.安装配置
  • 三、Supervisor配置步骤
  • 四、nginx 配置步骤
  • 五、Django管理后台admin
  • admin 模块原理
  • 一、注册模型
  • 二、先注册再路由
  • 三、admin 路由
  • 四、url 路由 include()函数
  • 五、总结
  • 六、python shell 和 django shell
  • 7 项目框架搭建&设计
  • django 使用多数据库
  • django 使用多个redis 缓存框架
  • 总结



前言

根据我的理解 python 优点是灵活性高 耦合性低 项目搭建方便简易,对环境依赖和部署方面非常灵活


一 、项目与环境配置

1.配置(pyenv 和 virtualenv)虚拟环境

配置安装pyenv 插件方便来管理切换主机环境中使用多个python版本。

使用pyenv 之前记得提前安装一个c语言的编译器 否者会报没有c语言编译器;
推荐 “gcc”,
apt-get install gcc

pyenv

git clone https://github.com/pyenv/pyenv.git ~/.pyenv --  ~/.pyenv  为下载到指定目录
-- 配置环境变量 bash shell方式
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc   -- 添加 PYENV_ROOT 系统环境变量
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc  --把刚下载的目录路径添加到PATH 系统环境变量。
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc
-- 配置环境变量 zsh shell方式
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.zshrc shell方式

此处 在作用 是把源码下载下来 然后 配置到系统环境变量中 这样就可以使用pyenv的命令了 与windows配置系统环境path一个意思。
pyenv-virtualenv

-- 要在pyenv的plugins目录下,下载
git clone https://github.com/pyenv/pyenv-virtualenv.git 
# 配置环境变量 bash
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
# 配置环境变量zsh
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc

此处的环境变量配置是初始化pyenv-virtualenv插件 (调用了pyenv中的初始化插件的方法)

2.创建指定py版本虚拟环境

创建python版本时的环境要求:

sudo apt-get install zlib1g-dev # 压缩工具
sudo apt-get install openssl # ssl 插件
sudo apt-get install zlib1g-dev
sudo apt-get install libssl1.0-dev # 1.0 ssl插件
sudo apt-get install make # make编译插件
sudo apt-get install libbz2-dev # 安装构建pyhton环境的时候需要的插件 tar.bz2

使用 pip install 安装的时候 都是通过官网源去查找whell文件下载安装的,但是你遇到的版本如果是其他格式,例如: tar.bz2 格式的压缩包 pip就会抛出未找到的错误。所以需要在构建python环境的时候把这些不同格式的工具包给构建进去。 让python环境支持安装这些格式的安装包。而不只支持whell文件下载

pyenv install -v 3.5.1  --用pyenv 安装指定版本python ,此处安装的版本都在pyenv的安装目录下,并且不会影响原来外部的python版本和环境。
pyenv uninstall 3.5.1 # 卸载指定python版本
--具体相关的pyenv命令请自行查阅
pyenv virtualenv 3.5.1 project_virtualenv_name -- 根据当前pyenv的py版本 创建对应的虚拟环境目录。  注意 创建的虚拟环境 默认只能在pyenv的安装目录下
pyenv virtualenv-delete envname  # 删除虚拟环境
pyenv activate project_virtualenv_name -- 进入到虚拟环境中
# 然后 到虚拟环境中安装项目依赖包
pip install -r requirements.txt
pip freeze > requirements.txt # 导出当前环境依赖

pip 导入项目依赖环境时 出现以下错误: 请升级pip版本,但是也别升级的太高需要符合你当前python版本支持范围内的pip版本。否则会警告消息

Command “python setup.py egg_info” failed with error code 1 in /tmp/pip-build-8ilg1ks6/cryptography

运行 python -m pip install --user --upgrade pip==20.0.3 //更新到指定版本
升级 setuptools 版本 pip install --upgrade setuptools
建议升级 否则安装插件模块会出错
卸载 python pip: python -m pip uninstall pip

这样 ,项目的独立的环境就创建好了,下面我们就可以使用uwsgi运行他了

二、Uwsgi配置步骤

1.安装配置

代码如下(示例):

sudo apt-get install uwsgi --(推荐)
--或者 
pip install uwsgi
--创建 uwsgi配置文件目录 
cd etc/uwsgi/seti
sudo vi uwsgi_test.ini --创建配置文件
uwsgi --ini uwsgi_test.ini  --启动项目
[uwsgi]
http = :8080
#the local unix socket file than commnuincate to Nginx
socket = 127.0.0.1:8000 # nginx代理到这里
# the base directory (full path)
#chdir = /home/ubuntu/webapps/.envBCS/BCS_TianYuan_Phenological_Chart/phenology
chdir = /datadrive/workspace/bcs/phenology #项目目录
# the virtualenv directory(full path)
#home = /home/ubuntu/webapps/.envBCS
home = /home/ubuntu/.pyenv/versions/bayer-bcs # 虚拟环境目录
# Django's wsgi file
#wsgi-file = /home/ubuntu/webapps/.envBCS/BCS_TianYuan_Phenological_Chart/phenology/phenology/wsgi.py
wsgi-file = /datadrive/workspace/bcs/phenology/phenology/wsgi.py # 项目wsgi文件目录
# maximum number of worker processes
processes = 4
#thread numbers startched in each worker process
threads = 2 # 线程
uid = root # 运行用户 
#monitor uwsgi status
stats = 127.0.0.1:9191
# clear environment on exit
vacuum = true
logto = /var/log/uwgi/bcs_uwsgi_django.log # 运行日志
[supervisord]
[supervisorctl]

此处,项目和 虚拟目录不一定非要放在一起,可以分开管理; 运行时uwsgi可以指定 环境版本和项目目录 这就是python的优点 ;大概 其他的后端语言,多多少少会出现 项目中需要带有依赖和第三方库吧 。(个人认为)

三、Supervisor配置步骤

代码如下(示例):

sudo apt install supervisor --(推荐)
--或者 
pip install supervisor
--默认会有 supervisor配置文件目录 
cd etc/supervisor
--生成supervisor配置文件
echo_supervisord_conf > /etc/supervisor/supervisord.conf

Supervisor的主配置文件

;[supervisord]
;logfile = /home/ubuntu/supervisord.log
;pidfile = /home/ubuntu/sup/supervisord.pid
;childlogdir = /home/ubuntu/sup/logs
[supervisord]
logfile = /datadrive/web-server/supervisor/logs/supervisord.log          ; (main log file;default $CWD/supervisord.log)
pidfile = /datadrive/web-server/supervisor/supervisord.pid               ; (supervisord pidfile;default supervisord.pid)
childlogdir = /datadrive/web-server/supervisor/logs
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=http://127.0.0.1:9001
[include]
files = conf.d/*.conf  --项目的子配置文件
[inet_http_server]
port = 127.0.0.1:9001

Supervisor的项目配置文件 conf目录

[program:bcs]  --bcs: 项目名称
;command=/home/ubuntu/.local/bin/uwsgi --ini /etc/uwsgi/sites/bcs.ini
--运行uwsgi的命令 指定运行哪个项目的配置文件
command=/home/ubuntu/.pyenv/versions/bayer-bcs/bin/uwsgi --ini /etc/uwsgi/vassals/bcs.ini
directory = /etc/uwsgi/vassals/  --uwsgi的配置文件目录
startsecs=0
stopwaitsecs=0
autostart=true
user=root --运行用户
autorestart=true
stderr_logfile=/var/log/bcs.err.log --supervisor 日志
stdout_logfile=/var/log/bcs.out.log
[supervisord]
[supervisorctl]
[inet_http_server]
port = 127.0.0.1:9001
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
--启动supervisor
supervisord -c /etc/supervisor/supervisord.conf --如果出现错误 请用以下命令
which supervisord --查询出supervisord的具体目录
sudo /home/ubuntu/.local/bin/supervisord -c /etc/supervisor/supervisord.conf  --指定目录和用户运行此命令即可

--启动django项目
supervisorctl start bcs --项目名称
--或者
supervisorctl -c /etc/supervisor/conf.d/bcs.conf start bcs 

--supervisorctl 是一个客户端命令 用于启动项目和查看项目运行状态
--supervisord 负责运行 conf.d目录下的配置文件

启动 supervisorctl 出现 错误信息:
error: <class ‘socket.error’>, [Errno 13] Permission denied: file:/usr/lib/python2.7/socket.py line: 228
解决方案: 使用sudo 或最高权限启动。

supervisorctl :常用命令

命令

说明

supervisorctl stop program_name

停止某个进程

supervisorctl start program_name

启动某个进程

supervisorctl restart program_name

重启某个进程

supervisorctl stop all

停止全部进程

supervisorctl reload

载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程

supervisorctl update

根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启

如果使用sock文件交互的话需要如下步骤:
supervisor 不会自动生成sock文件,只会写入 需要自行创建。

sudo touch /var/run/supervisor.sock
sudo chmod 777 /var/run/supervisor.sock
sudo service supervisor restart

四、nginx 配置步骤

nginx 代理到 uwsgi 运行的端口上即可。

upstream uwsgidjangoservers4ynh {
    ip_hash ;
    server 127.0.0.1:8000;
}
server {
    listen 80;
    listen [::]:80;
    server_name expoer.com;

     location / {
         include             uwsgi_params;
        uwsgi_pass          127.0.0.1:8000;
     }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

如果访问后台管理系统出现错误,请检查代码中是否有token中间件校验影响了。
如果出现跨域错误: 请查看django setting 配置文件 ALLOWED_HOSTS 跨域参数是否配置。

五、Django管理后台admin

Django最大的优点之一,就是体贴的为你提供了一个基于项目model创建的一个后台管理站点admin。我们可以在这个管理后台对内容进行查看、添加、修改、删除数据等操作,能让你节省大量开发时间。而且Django能够根据定义的模型类自动地生成管理模块。

1、创建管理员帐号密码

python manage.py createsuperuser

输入用户名:

Username: admin

输入邮箱地址:

Email address:vip@django.cn

输入密码:

Password: **********
Password (again): *********
Superuser created successfully.

注意:超级用户的密码强制要求具备一定的复杂性,否者验证不通过。
访问 127.0.0.1:8000/admin即可登录系统

2、注册admin注册blog应用
现在后台,只有默认的Django认证和授权应用,我们前面设计的那个应用模型我们需要在管理后台注册之后才能对其进行管理。
方法如下:

打开应用/admin.py文件,加入如下内容:
每个应用目录下都有一个admin.py文件 都可以使用以下方式注册到admin系统中进行管理

from django.contrib import admin
from .models import Article,Tags,Category --模型
admin.site.register(Tags)
admin.site.register(Article)
admin.site.register(Category)

刷新页面,我们就能看到blog这个应用了。

python virtualenv 激活命令 virtualenv指定python版本_python

admin 模块原理

配置admin 首先在项目的app下的admin中注册需要管理的模型类。
url 中引入admin_url

一、注册模型

如图所示

from django.contrib import admin
from . import models
class zhangsan(admin.ModelAdmin):
    list_display = ('name', 'email')
    list_editable = ('email',)
    search_fields = ["name"]
    date_hierarchy = 'ctime'
admin.site.register(models.UserInfo,zhangsan)

site = AdminSite()

# 注册函数
def register(self, model_or_iterable, admin_class=None, **options):
    if not admin_class:
        admin_class = ModelAdmin
    if isinstance(model_or_iterable, ModelBase):
        model_or_iterable = [model_or_iterable]
    for model in model_or_iterable:
        if model._meta.abstract:
            raise ImproperlyConfigured(
                'The model %s is abstract, so it cannot be registered with admin.' % model.__name__
            )

        if model in self._registry:
            raise AlreadyRegistered('The model %s is already registered' % model.__name__)
        if not model._meta.swapped:
            if options:
                options['__module__'] = __name__
                admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
            self._registry[model] = admin_class(model, self)

1、admin会通过admin.site.register(models.类名,模板类)的方式来注册models中的类。从源码中可以看出,如果我们没有写模板类的话源码就会默认继承ModelAdmin这个模板类,如果我们写了模板类的化也是在继承ModelAdmin这个类的基础上修改模板。

2、由django admin源码可知site其实是个对象,该对象是个单例模式,而admin.site.register(x,y)实际是admin通过site对象来调用site对象下的register方法,并且还传入了x,y两个参数,其中x指的是models中需要注册的类名,y指代的是注册的类需要使用的模板类。

3、通过源码 self._registry[model] = admin_class(model, self)就可以看出admin.site.register(x,y)最终得到的结果是个字典,其中字典的k指代的是注册的类,字典的v指代的是模板类实例化产生的对象,而为这个对象传递进去的参数是注册的类

总结:admin中注册的最终目的是生成一个字典,字典的k是注册的类,v指的是模板类实例化产生的对象,并且为这个对象传递进去的参数是注册的类

二、先注册再路由

参考链接:原理 戳这里 1、为什么会先注册models中的类,再执行路由函数是因为在admin模块中有如下代码:

def autodiscover():
    autodiscover_modules('admin', register_to=site)

总结:该代码的作用就是告诉django先执行admin.py文件内的代码,注册好类后再执行路由函数

1. 先执行admin.py,使用单例模式创建一个admin.site的对象
2. 在admin.site对象中,把admin.py中定义的类全部注册,并把类中所有的配置全部传递到admin.site对象的_registry生成的字典中
3. 在生成url时,url会循环site中的类,为每一个类生成相应的url

参考链接

三、admin 路由

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
@property
def urls(self):
return self.get_urls(), 'admin', self.name

def get_urls(self):
from django.conf.urls import url, include
from django.contrib.contenttypes import views as contenttype_views
def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)
 wrapper.admin_site = self
return update_wrapper(wrapper, view)
 urlpatterns = [
 url(r'^$', wrap(self.index), name='index'),
 url(r'^login/$', self.login, name='login'),
 url(r'^logout/$', wrap(self.logout), name='logout'),
 url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
 url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
 name='password_change_done'),
 url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
 url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
 name='view_on_site'),
 ]
for model, model_admin in self._registry.items():
 urlpatterns += [
 url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
 ]
if model._meta.app_label not in valid_app_labels:
 valid_app_labels.append(model._meta.app_label)
if valid_app_labels:
 regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
 urlpatterns += [
 url(regex, wrap(self.app_index), name='app_list'),
 ]
return urlpatterns

1、通过路由系统中的admin.site.urls可知admin路由系统调用的是site对象下的urls方法。而通过源码可知该方法返回了三个值 self.get_urls(), ‘admin’, self.name,而第一个值执行了个函数,该函数的最终目的的将一个列表返回,而列表内嵌套的是一个个的元组,元组内嵌套的是一个个的url路径。

2、model.类名._meta.app_label得到的是项目名称,model.类名._meta.model_name得到的是类名称

3、通过admin的路由系统最终给我们的是个列表内嵌套元组,每个元组内有x,y两个元素,x是生成的对于类的url,y是include()函数,并且向该函数内传递了

四、url 路由 include()函数

如图所示,include()函数源码

def include(arg, namespace=None, app_name=None):
    if app_name and not namespace:
        raise ValueError('Must specify a namespace if specifying app_name.')
    if app_name:
        warnings.warn(
            'The app_name argument to django.conf.urls.include() is deprecated. '
            'Set the app_name in the included URLconf instead.',
            RemovedInDjango20Warning, stacklevel=2
        )
 
    if isinstance(arg, tuple):
        # callable returning a namespace hint
        try:
            urlconf_module, app_name = arg
        except ValueError:
            if namespace:
                raise ImproperlyConfigured(
                    'Cannot override the namespace for a dynamic module that provides a namespace'
                )
            warnings.warn(
                'Passing a 3-tuple to django.conf.urls.include() is deprecated. '
                'Pass a 2-tuple containing the list of patterns and app_name, '
                'and provide the namespace argument to include() instead.',
                RemovedInDjango20Warning, stacklevel=2
            )
            urlconf_module, app_name, namespace = arg
    else:
        # No namespace hint - use manually provided namespace
        urlconf_module = arg
 
    if isinstance(urlconf_module, six.string_types):
        urlconf_module = import_module(urlconf_module)
    patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
    app_name = getattr(urlconf_module, 'app_name', app_name)
    if namespace and not app_name:
        warnings.warn(
            'Specifying a namespace in django.conf.urls.include() without '
            'providing an app_name is deprecated. Set the app_name attribute '
            'in the included module, or pass a 2-tuple containing the list of '
            'patterns and app_name instead.',
            RemovedInDjango20Warning, stacklevel=2
        )
 
    namespace = namespace or app_name
 
    # Make sure we can iterate through the patterns (without this, some
    # testcases will break).
    if isinstance(patterns, (list, tuple)):
        for url_pattern in patterns:
            # Test if the LocaleRegexURLResolver is used within the include;
            # this should throw an error since this is not allowed!
            if isinstance(url_pattern, LocaleRegexURLResolver):
                raise ImproperlyConfigured(
                    'Using i18n_patterns in an included URLconf is not allowed.')
 
    return (urlconf_module, app_name, namespace)

1、由include()函数源码可知,include函数返回的是个(urlconf_module, app_name, namespace)元组,urlconf_module的本质是个模块,通过这行代码可以看出:urlconf_module = import_module(urlconf_module),

2、urlconf_module模块的本质其实就是列表内嵌套一行行的url,由此可得知include()函数的作用其实就是路由重分发,而路由重分发得到的数据格式其实就是如下所示:

url(r'^app01/', ([
               url(r'^userinfo/', ([
               url(r'^index/', index,name='idx_xxx_f'),
               url(r'^test/', test,name='tst'),],'x2','x2')), ],'x1','x1')),

五、总结

如果出现多个django应用的admin后台管理系统。
通过调整路由来代理

urlpatterns = [
    path('admin/', bayer_crawler_admin_site.urls),
]
  1. “admin/” 可以自定义来区分不同admin系统。
    系统中的增删改查功能和页面模板都是通过此admin_urls实现的。
  2. 静态资源css和js 可以统一使用。
  3. media 上传资源

六、python shell 和 django shell

不论在生产环境还是测试环境难免会遇到需要扩展或导数据的操作。但是,我们又不想直接操作数据库, 况且生产环境的数据库是不允许远程连接的。这样一来就体现了,django shell的优势。
python 也有自己的shell django 也有自己的shell
django shell中 使用admin.py在django项目中设置环境和配置文件,以便您可以与shell中的项目对象交互。
python shell 中 我们可以导入并执行我们想要的。
!!注意: 在多个环境的项目中 内部肯定包含不同环境的配置文件 此时 django shell 需要指定配置文件

django 启动时默认使用setting 如果你有多个此文件 启动时就需要指定文件,例如以下:

DJANGO_ENV='test' python manage.py shell  --settings=iCrawler.settings_test

python shell

C:\Users\亚晨>python
Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

django shell

DJANGO_ENV='test'  python manage.py shell 
或者
DJANGO_SETTINGS_MODULE python manage.py shell # 执行django的配置文件
# 结果如下:
DJANGO_ENV='test' python manage.py shell
[2021-02-02 02:44:07,320:31175]:INFO:root::[ip-173-0-0-218] use config [/home/ubuntu/bayer_ynq/BCS_YNQ_Service/config/yaml/crawler_server.test.yaml]
[2021-02-02 02:44:07,363:31175]:INFO:root::[crawler_server.base] is imported ~
/home/ubuntu/.pyenv/versions/crawler_3.5.1/lib/python3.5/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
  """)
/home/ubuntu/.pyenv/versions/crawler_3.5.1/lib/python3.5/site-packages/IPython/core/history.py:226: UserWarning: IPython History requires SQLite, your history will not be saved
  warn("IPython History requires SQLite, your history will not be saved")
Python 3.5.1 (default, Jan 29 2021, 06:17:17) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:exec(open('exporter.py').read())   # 在django shell中执行外部py文件

如果你在django shell中 使用orm的事务了,并且django项目中的数据库有多个,则使用事务需要指定数据库
with transaction.atomic(‘operation’): # operation参数 为setting 数据库配置中的参数名。
默认 atomic方法会走default参数的配置

orm事务详解django shell 执行外部文件

7 项目框架搭建&设计

企业开发中: 分为 开发、测试、预发、生产等环境
那么我们不能为每个环境创建不同的应用岂不是一件头疼的事情,并且还影响 git 代码管理也特别的繁琐。
为了使项目能够使用多种环境,我们可以使用以下架构模式:
项目的基础配置文件 (如: 数据库连接串,redis 连接串等)
创建不同环境的project.yaml基础配置文件
创建不同环境的setting.py文件
创建不同环境的 requirements 环境依赖文件
创建不同环境 celery_config 配置文件
最后根据DJANGO_ENV 环境变量 动态加载不同环境的配置文件
使用启动 uwsgi 设置 DJANGO_SETTINGS_MODULE 环境变量 来指定配置文件

django 使用多数据库

使用using(‘setting文件database连接名’)

django 使用多个redis 缓存框架

参考 戳这里 想使用多个redis,需要使用django-redis 扩展包的api来使用。django自身无法操作多个缓存框架。
单独的想接管django的cache的话在setting下配置:

1. 单体cache框架
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": CONFIG('DJANGO_REDIS.CACHE_LOCATION'),
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}
# 此时django的cache 直接被redis给接管了。
使用: 
from django.core.cache import cache  # 引入缓存模块
cache.get('key')
cache.set('key','value','expiration_time')
2. 集群式cache框架
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": CONFIG('DJANGO_REDIS.CACHE_LOCATION'),
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    "ynt": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": CONFIG('YNT_REDIS.CACHE_LOCATION'),
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
使用:
from django.core.cache import cache # 还是使用setting中default项
from django_redis import get_redis_connection #使用此模块 实现创建指定连接实例。
redis_conn = get_redis_connection('ynt')
redis_conn.get()
redis_conn.set()

总结

python的优点 : 部署, 管理 比较灵活。
Django项目集成了比较强大的依赖库 又实现了环境的单元性与docker类似。
此处相关的配置文件的坑 主要是 supervisor和uwsgi。
会出现 日志权限,配置中没有指定端口和http等错误。
可以查看对应的配置文件排错。

Django 项目中 可以创建多个应用目录实现应用的复用。具体了解可以查看官网 工程的介绍
Django官网