.. _django_mysql: ========================== Django配置MySQL数据库 ========================== 在部署 :ref:`django_env_linux` 后,我们可以开发Django。但是,默认使用的数据库是sqlite,和生产环境往往不同。所以,我们通常会把Django数据库后端替换成MySQL。 但是,需要注意的是,我们不能把数据库访问账号密码直接配置在 ``manage.py`` 中,也不能把包含账号信息提交到git仓库中,所以需要有一定的配置方法来实现数据库连接。 准备数据库 ============== - 使用以下方式创建应用数据库:: create database myappdb character set utf8; create user myapp@'%' identified by 'MyPass'; grant all privileges on myappdb.* to myapp@'%'; flush privileges; 安装mysqlclient模块 ==================== 在安装 :ref:`virtualenv` 之后,通过 ``pip`` 安装 ``mysqlclient`` 模块:: pip install mysqlclient 如果出现报错:: ERROR: Command errored out with exit status 1: command: /home/admin/venv3/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-3m5z471x/mysqlclient_891b537df843484ba930dc9520c76710/setup.py'"'"'; __file__='"'"'/tmp/pip-install-3m5z471x/mysqlclient_891b537df843484ba930dc9520c76710/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-1mbvlvf_ cwd: /tmp/pip-install-3m5z471x/mysqlclient_891b537df843484ba930dc9520c76710/ Complete output (15 lines): /bin/sh: mysql_config: command not found /bin/sh: mariadb_config: command not found /bin/sh: mysql_config: command not found mysql_config --version mariadb_config --version mysql_config --libs 则需要安装 mysql 开发包,例如 ``mariadb-devel`` ,安装以后系统会有 ``mysql_config`` 工具: .. literalinclude:: django_mysql/install_mysql-devel :caption: 需要提前安装 ``mysql-devel`` 或 ``mariadb-devel`` 才能执行 ``pip install mysqlclient`` .. note:: 在 :ref:`django_env_linux` 对于 ``pip install mysqlclient`` 有处理案例 .. warning:: 我最近的实践发现在CentOS 7环境提供的是 MariaDB,此时编译安装 ``mysqlclient`` 模块始终报错,参考 `How to connect Python programs to MariaDB `_ ,看起来社区采用了新的 ``mariadb`` 来连接MariaDB,我以为 ``mysqlclient`` 已经不能兼容。 **实际上并不是这样** , ``mysqlclient`` 需要采用 ``MariaDB`` 的较高版本才能正常编译。我验证 :ref:`install_mariadb` v10.11 则编译安装没有任何问题。 解决 ``mysqlclient`` 模块安装 ------------------------------ .. warning:: 我这里的挫折实际上是因为我采用了CentOS(aliOS 7.2)发行版内置的 ``MariaDB`` v5.5 导致的,浪费了我两天时间。实际上,当重新 :ref:`install_mariadb` v10.11 之后问题引刃而解。 这次遇到一个报错,和之前 :ref:`django_mysql` 不同: .. literalinclude:: django_env_linux/mysqlclient_error :caption: ``pip`` 安装 ``mysqlclient`` 报错 :emphasize-lines: 10-13 这里可以看到 ``pkg-config --exists mysqlclient`` 和 ``pkg-config --exists mariadb`` 都是返回 ``1`` (失败)。我手工执行了一下,确实 ``echo $?`` 显示 ``1`` 仔细一看,原来这个 ``pkg-config`` 是操作系统默认的 ``/usr/bin/pkg-config`` 。这里通过 ``rpm -qf /usr/bin/pkg-config`` 可以看出是属于 ``pkgconfig-0.27.1-4.1.alios7.x86_64`` ,显然不会获得正确的包信息 `PyMySQL / mysqlclient / README.md `_ 提供了一个线索: .. literalinclude:: django_env_linux/pkg-config_mysqlclient :caption: 定制编译时指定环境变量 既然由于操作系统的 ``pkg-config`` 无法正常工作,那么该如何设置环境变量呢? 我找了自己部署的一台 :ref:`fedora` 开发环境( :strike:`吐槽一下公司魔改的CentOS` 社区CentOS 7确实存在这个问题),可以看到: .. literalinclude:: django_env_linux/pkg-config_mariadb :caption: 在正确的环境中执行 ``pkg-config`` 获取环境变量 :emphasize-lines: 2,4 - 所以修正安装方法: .. literalinclude:: django_env_linux/pkg-config_mariadb_env :caption: 设置正确 ``mysqlclient`` 环境变量 - :strike:`然后再次执行就可以完成` 不过我再次执行安装报错似乎不兼容: .. literalinclude:: django_env_linux/mysqlclient_error_again :caption: 提供了mysqlient的编译环境变量,但是编译报错 :emphasize-lines: 46-55 这个问题我最后做了多次安装对比,发现是旧版本 ``mariadb`` 的bug,当采用 :ref:`install_mariadb` 采用社区仓库并安装 MariaDB 10.11 之后,这个问题引刃而解。 配置Django连接数据库 ===================== - django一般有2种方式获取数据库连接信息: - 直接读取 ``/etc/my.cnf`` (当前Django官方推荐) : 例如这里可以创建一个 ``myapp.cnf`` 配置文件,对应上文创建的 ``myappdb`` 数据库访问账号 - 使用环境变量 .. _django_mysqlclient_config: Django使用MySQL Client配置(推荐) ----------------------------------- 现在Django推荐采用直接读取操作系统安装的MySQL客户端配置来完成数据库连接配置。例如,通常我们的数据库访问配置 ``/etc/my.cnf`` 内容如下:: [client] database = NAME user = USER password = PASSWORD default-character-set = utf8 - 修改 ``myapp/settings.py`` 数据库配置:: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'OPTIONS': { 'read_default_file': '/etc/onesredb.cnf', }, } } Django使用数据库环境变量 --------------------------- django支持从环境变量中读取配置,所以可以将密码相关变量保存到环境中。对于使用Python virtualenv,可以在进入虚拟环境的最后激活配置 ``postactivate`` 中设置环境,并在 ``predeactivate`` 文件中 ``unset`` 环境变量。 - 修订django的 ``myapp/settings.py`` 将:: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } 修改成:: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': get_env_variable('DATABASE_NAME'), 'USER': get_env_variable('DATABASE_USER'), 'PASSWORD': get_env_variable('DATABASE_PASSWORD'), 'HOST': '', 'PORT': '', } } - 在 ``myapp/settings.py`` 开头加上:: from django.core.exceptions import ImproperlyConfigured def get_env_variable(var_name): try: return os.environ[var_name] except KeyError: error_msg = "Set the %s environment variable" % var_name raise ImproperlyConfigured(error_msg) - 最后在virtualenv虚拟机环境 ``venv3/bin/postactive`` 中加上数据库设置:: export DATABASE_NAME='myappdb' export DATABASE_USER='myapp' export DATABASE_PASSWORD='MyPass' - 并在virtualenv虚拟机退出配置 ``venv3/bin/predeactivate`` 配置加上:: unset DATABASE_NAME unset DATABASE_USER unset DATABASE_PASSWORD 数据库迁移 ------------- 在完成上述两种数据库连接配置之一后,执行以下命令进行数据库migration:: python manage.py migrate 最后测试应用启动:: python manage.py runserver 参考 ====== - `Install and Configure MySQL for Django `_ - 通过环境变量设置数据库连接 - `How To Create a Django App and Connect it to a Database `_ - `Connecting to the database `_