推荐下目前在用的云存储厂商又拍云

最近在做一个 https://packagist.org 的镜像,所以需要一个CDN来做国内加速。国内比较适合的也就七牛和又拍云了。

作为CDN

后来比较了下,发现七牛仅仅是做存储,它会忽略用户设置的超时时间(Cache-Control 字段)。而又拍云则会遵守源站的缓存设置。

比如我如果设置我的url缓存为5min,那又拍云就只会保留缓存5min。

在这一点上,又拍云就做的非常好,可以选择存储模式,也可以选择CDN模式。当然,更重要的一点是有免费额度。相比七牛的免费额度来讲,确实比较宽裕。

比如,我的这个项目,源站是在我的vps上,接受http访问。那我只需要将空间的回源设置如图即可:

支持SSL/TLS

为了让我的域名支持SSL/TLS,我只需在云拍云上花费0元购买Let’s Encrypt的SSL证书,然后补全信息即可。

如图:

我绑定了又拍云,然后又拍云直接向Let’s Encrypt申请DV证书,绑定到域名就行。

相比其他服务商,需要手动上传服务器证书,确实方便了很多。而且自己手动申请的Let’s Encrypt证书,需要每90天更新一次,所以还是直接交给又拍云比较方便。

云存储

和云存储厂商一样,又拍云也提供了对象存储服务。

基本的文件操作都是支持的。当然,也必须支持断点续传,对于上传大文件来说,这个尤其方便。

还可以给文件添加各种自定义的元数据,比如我可以给文件设置x-upyun-meta-sha512: 123456,可以参考https://docs.upyun.com/api/rest_api/#metadata

但是这儿也有一些坑:

比如,获取文件信息:

MD5算法确实有很严重的漏洞,容易产生重复的哈希值。建议又拍云下一版换成sha512算法。

还有,如果我设置了自定义元数据,比如x-upyun-meta-sha512: 123456,那我只能通过下载文件接口来获取这个元数据,通过获取文件信息接口反而没有自定义的元数据,这一点很不方便。

文件拉取

做镜像的过程中,很重要的一个点就是文件拉取。

比如,我要代理laravel的下载地址:https://github.com/laravel/framework/archive/v5.5.13.zip,我只需要将url拉取到又拍云上对应的地址就好。

但是,由于要使用回调,在调试的时候很不方便,所以目前我用的比较少。

建议又拍云在拉取文件的时候,给拉取任务一个id,然后客户端根据这个id查询拉取状态,会方便开发。

又拍云重度用户

这个项目很依赖CDN,所以很耗流量。


最后,附上我的邀请链接:

https://upyun.com/

Cannot install MySQL-python at macOS 10.13 Beta

Round #1

Complete output from command python setup.py egg_info:
    sh: mysql_config: command not found

Solution

brew install mysql
# or
brew reinstall mysql

Round #2

clang -bundle -undefined dynamic_lookup ****/_mysql.o -L/usr/local/Cellar/mysql/5.7.18_1/lib -lmysqlclient -lssl -lcrypto -o build/lib.macosx-10.12-x86_64-2.7/_mysql.so
ld: library not found for -lssl

Solution

brew install openssl
export LDFLAGS="-I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib"
pip install mysql-python

Sometimes, you need xcode-select --install

[译]输入系统如何工作——指针输入

翻译自 How input works – pointer input

上一篇博文中,我讨论了键盘输入。这篇博文将会讨论指针设备——多被称为鼠标。就像本系列文章一样,本文仅仅讨论了KWin/Wayland上面的情形。

不同的硬件类型

有好几种不同的设备被识别为指针设备。有轨迹球这样的传统鼠标,也有在笔记本上的触摸板。此外,还有可绝对定位的设备,比如触摸屏。

在libinput中,对于不同的设备,有很多不同的选项可供配置。比如指针加速等其他选项。我们正在开发Wayland的触摸板配置模块,看起来会合并到Plasma 5.9中。像第一篇博文描述的,一旦设备创建,一系列配置选项会被立马设置。

指针运动

指针设备生成不同种类的事件,其中一种就是指针运动事件。通常来说,有两种指针运动事件:绝对运动和相对运动。大多数设备,比如鼠标,产生相对运动事件,所以我们在本文中只关注相对运动事件。

确定新的位置

相对运动是一组带x和y坐标的距离向量,它描述了指针位置该如何移动。

所以,一旦事件从KWin队列中读取出来,需要确定新的指针位置。这并不单单是最后的指针位置再加上一个运动向量。这会导致指针离开可视区域。

相反,指针运动得验证和约束。我们确保光标不会离开可视区域,并且还要遵守应用程序窗口对指针的约束。

这是KWin在Plasma 5.9中支持的新协议。它允许Wayland窗口将指针锁定到某个位置或将指针限制在某个区域。在第一种情况下,指针根本不移动,在第二种情况下,只允许指针在窗口的特定区域移动。

处理新的位置

即使在光标被限定的情况下,不需要移动鼠标指针,事件也会得到进一步处理。即使光标不移动,应用程序也可能对相对运动感兴趣,并对其做出反应。

像键盘的情况一样,为了进一步处理,会生成QMouseEvent并发送到KWin的输入过滤器。指针运动可能在KWin内部处理,例如:指针位置超出了当前的屏幕边缘。或者通过KWayland将指针运动转发到窗口。

更新获取焦点的窗口

如果指针移动,光标可能从一个窗口移动到另一个窗口,或从窗口移动到Wayland服务器端的窗口装饰上。这意味着对于每个指针位置的变化,KWin需要计算当前位置的窗口。

与键盘输入相比,KWin只需要考虑活动窗口,但这也是一个相当复杂的任务。我们需要考虑将输入变换应用于屏幕还是窗口,我们需要在窗口上应用输入掩码,考虑窗口装饰,检查屏幕是否被锁定,Xwayland 1.18之前的临时解决方案等一大堆问题。

最后,该方法可能已经确定了一个获得指针焦点的新平面。KWin使用KWayland来更新聚焦的指针表面,确保离开旧表面和进入新平面的事件触发。

当然,当移动鼠标时,应该更新焦点。如果拖放(按下指针按钮并移动),则不会更新焦点。

更新指针图案

如果指针移动到新的位置,指针图标有可能会改变。不幸的是,这可能需要多次往返消息才能确定。窗口管理器不知道窗口想要使用哪个指针图标,直到动作被发送到窗口。一个窗口可以通过两种方式做出反应:它可以更新光标图像,也可以不更新。在第一种情况下,KWin通过KWayland通知图像发生变化,在第二种情况下根本没有通知。

这意味着移动光标时,KWin不知道光标图标是否是正确的。所以在指针运动时,KWin更新光标到新的位置,但是光标图标仍然是旧的,但可能在一帧之后,客户端就会更新光标图案了。不得不说,在Wayland的显示下,并不是每一帧都是完美的,这是我遇到的唯一一个此类情况:光标可能显示错误的图标。

进入窗口时,光标尚未定义。直到窗口设置光标,否则光标还是未设置的状态。此时,KWin不会渲染光标;这意味着当进入冻结窗口(程序无响应的窗口)时,我们没有光标。我们以后必须改进这一点。目前,我们没有检测挂起的应用程序,因为我认为我们无法检测到它们:客户端使用专用的Wayland事件线程,因此程序可以永远给一切事件回复OK,即使事件并没有处理。

但是,KWin也可能需要设置一个光标图像。例如,当鼠标在窗户装饰上悬停,或进入特殊模式以选择窗口时,就使用KWin提供的光标图像。KWin从主题中加载这个光标图案。在内部,KWin记录光标图案应该使用的源图像。无论是Wayland窗口还是窗口选择界面,还是使用特定的光标图像。

更新实际光标

通过KWin的内部平台API实现光标位置和图标的实际更新。每个平台以不同的方式设置光标图像。对于我们的主要平台,我们使用DRM API来更新位置并更新图标——如果有新图标的话。

对于Wayland中嵌套的X11这样的嵌套平台,这通过窗口系统内的特定的调用处理。嵌套平台不允许更新光标位置——这是由窗口系统之间通过指针运动间接更新的。但是,光标图案可以更新。

虚拟出来的平台只知道软件指针的概念。这是在合成器渲染过程中渲染出来的光标。目前这只有在QPainter合成器中实现,在OpenGL合成器中还没有实现。

按钮事件

libinput支持指针设备产生的指针按钮的按下、释放事件。这些事件携带着它们触发的指针按钮。

和指针运动事件相比,按钮事件的处理更加直接。指针事件被事件过滤器拦截(比如Alt+Tab)或者被转发到当前获取焦点的窗口。

这相比于X11,是一个巨大的进步。在X11下,如果KWin希望独占的处理指针事件,则需要锁定指针。这意味着屏幕无法锁定。如果当前窗口处于活动状态,屏幕不锁定。在Wayland,这并不重要。如果当前窗口处于活动状态,屏幕可以锁定,也可以获取所有指针事件。一旦解锁当前的窗口仍然是活动窗口。“我”很轻松地为这种情况添加了自动测试。

轴事件

许多指针设备有一个或者两个轴。在X11的核心协议中,轴事件被实现为指针按钮。在Wayland和libinput的情况下,我们有了自己的轴事件,能告诉我们哪个轴被移动了,移动了多少。这是一个很大的提升,相比于X11,这意味着“平滑滚动”是标准的一部分了,在滚动事件的处理过程中,额外的事件处理部分也不会执行。

其他事件的处理也非常简单。KWin创建了一个QWheelEvent并将其传递给许多事件过滤器,如果过滤器没有拦截事件,它会被转发到KWayland::Server,KWayland::Server再把事件发送到获得焦点的指针平面。

触摸板手势

对于触摸板,我们还有别的事件。对于触摸板,Libinput不仅仅识别运动事件和按压事件,还能识别多指手势。它支持两种手势:滑动手势,捏合/旋转手势。KWin获取手势事件,转发给正常的事件系统。我们在Wayland协议中添加了特殊的支持。这允许转发鼠标手势Wayland应用程序,如视频所见。

很不幸,我们还没有真正地使用这些手势。QtWayland没有实现这个协议,所以转发的消息并不会到达应用程序,我们还没有使用它,比如全局手势就没有使用,我们仍在努力界定我们要支持的手势。我希望我们在Plasma 5.9能够改进这点,但是这也不确定。

假期愉快

这是“我”今年的最后一篇博客。下一年我将继续这一系列博客,会谈谈触摸屏事件,或许会包括数位版。

“我”希望每个人都有一个愉快的假期,在2017年有一个不错的开始。

如果你想支持“我”的工作,请考虑捐款。让世界变得更好!——KDE 2016年末募捐

如何在Linux/Fedora下编译安装为知笔记

虽然为知收费了,但是目前只有为知笔记的Linux客户端做的不错,也只能用它了。

首先,安装编译期间的依赖:

# git拉代码,cmake编译
sudo dnf install -y git cmake
# 编译器
sudo dnf install -y gcc gcc-c++
# qt5相关的包
sudo dnf install -y qt5-qtbase-devel qt5-linguist qt5-qtwebengine-devel qt5-qtwebsockets-devel

sudo dnf install -y zlib-devel

拉代码(此处以v2.5.0分支为例):

git clone https://github.com/WizTeam/WizQTClient.git
cd /path/to/WizQTClient
git checkout v2.5.0

编译:

# 安装到~/.local/目录
cmake . -DCMAKE_INSTALL_PREFIX=$HOME/.local/
# -j 参数加速编译
make -j $(nproc)
# 安装
make install

安装完成后,为知笔记位于$HOME/.local/bin/WizNote,也可以在应用列表中找到。


  • 编译的时候cmake检测模块不通过,会提示如下错误:
CMake Error at cmake/QtChooser.cmake:1 (find_package):
  By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt5", but
  CMake did not find one.
  Could not find a package configuration file provided by "Qt5" with any of
  the following names:
    Qt5Config.cmake
    qt5-config.cmake

你只需要通过dnf provides */Qt5Config.cmake 命令来找找哪个包提供了,比如qt5-qtbase-devel

  • make的时候会报:
lib/quazip/zip.h:56:18: fatal error: zlib.h: No such file or directory
 #include "zlib.h"

也是一样的处理方式,使用dnf provides */zlib.h 找到包,比如zlib-devel

  • 为什么使用 $HOME/.local/ 作为安装目录:

首先,/usr/local 作为安装目录,需要root权限才能安装,删除的时候也不好删除,因为/usr/local/ 下可能也有别的软件。

其次,/opt/wiznote 作为安装目录,也需要root权限,而且也会导致wiznote.desktop中申明的图标名称找不到。

$HOME/.local/ 作为安装目录,生成的wiznote.desktop开箱即用,也不需要root权限,比较方便。

[译]输入系统如何工作——键盘输入

本文是 How input works – Keyboard input 的翻译。

上一篇博文中,我[作者]解释了KWin中,输入设备是如何打开和处理的。在这篇博文中,我们将仔细关注下键盘设备和键盘事件。

键盘并不总是键盘

在Linux中,键盘是一个非常奇特的设备。你不会只有一个键盘,你肯定会有很多个。很多设备宣称自己是键盘,但是只支持一个键。比如,电源按钮或者带静音按钮、音量加减按钮的外置耳机。从输入系统的角度来看,这些设备也是键盘。

对于KWin,发现真正支持的键盘是很重要的。如果没有一个“真的”键盘连接(或者说开启),我们的虚拟键盘应该自动激活。比如,如果你从平板PC二合一设备上拔了键盘,它应该转换为平板模式,即有虚拟键盘的模式。如果连接上了键盘,虚拟键盘就不是主要的输入设备了。libinput提供了函数来检测键盘支持哪些键。我们使用这个功能来区分不同的键盘类型。

键盘事件

在这里,键盘是最简单的输入设备。libinput仅仅触发一个LIBINPUT_EVENT_KEYBOARD_KEY事件,并包含了被按下或者释放的键。KWin有一个专用线程,用来从libinput读取事件。所以这些事件现在仅仅是放在处理队列中,主线程同时也得到新事件通知。一旦主线程处理事件,事件就被转换成我们的输入重定向类。不管事件是通过哪种源头抵达,所有输入事件都会通过输入重定向。KWin不仅仅支持来自libinput的事件,并且支持嵌套会话(即KWin运行在X11之上,或者在另一个Wayland服务器之上),还有在集成测试中使用的模拟事件。这意味着一旦事件到达输入重定向,我们基本上就丢失了事件来自哪个设备这些信息。最近,我们扩展了内部API,可以在事件处理函数中包含设备源,这是可选的。可以在调试终端中使用,来显示哪些设备产生了哪些事件。

xkbcommon

现在,一个键的按下、释放事件到达了中心分发方法KeyboardInputRedirection::processKey。第一件也是重要的一件事就是在xbkcommon中更新键盘状态。xkbcommon被用将物理键为事件,转换过程根据键盘布局、键盘状态(比如激活的修饰符)来进行。比如:如果我按下了“y”键(键码是21)并且“Shift”键是按下的状态,在德语键盘布局下,就会创建“Z”按下的事件;但是在英语键盘布局下,它会是“Y”。

在KWin中,我们将所有需要的xkbcommon功能都封装到Xkb类中。这个类追踪活跃的键盘布局、执行键盘布局切换(当布局变换的时候展示OSD)。它知道上一次按键的符号,当前活跃的修饰符和快捷键相关的修饰符。

当xkb的状态更新的时候,我们也检查很多键盘状态变更。用户是不是激活了数字锁定?如果是这样,我们需要让键盘上的LED做对应的变化,所以我们的libinput代码能够更新物理键盘上LED的状态。修饰副是不是变掉了?如果是这样,我们要将新的修饰符集合通知给Wayland窗口。尽管实际上从key到符号的翻译发生在Wayland客户端,但刚刚讲的翻译过程也在Wayland服务端进行了。为什么KWin也要做这一层翻译呢?这是因为KWin也需要在很多地方使用键盘符号,比如在当前窗口中过滤按键,来实现全局快捷键。

调试终端中的键盘状态

Xkb状态更新功能也能够处理哪些只需要修饰符键就能触发的快捷键。实际上,在这儿处理是不对的,但我们的输入过滤代码没法保证能捕获到所有的输入事件。对于快捷键中的修饰符,看多所有的事件是很基础的需求。所以,唯一的处理地方只能在Xkb中了。这不是最优雅的解决方案,但是能工作。这个功能也被X11使用,我在之前的博文中讲过。

KWin的过滤

现在KWin有足够的信息来处理键盘事件。对于此,它创建自定义的QKeyEvent并将其送到输入过滤链。KWin的输入处理使用了输入过滤器组成的链。每个过滤器都能够对事件做一系列操作,并决定这个事件是不是应该被继续处理,或结束处理。

比如,我们有锁屏过滤器。如果屏幕是锁屏状态,这个过滤器就会过滤事件处理,确保事件只会被送到屏幕锁定程序,不会被其他窗口处理。或者这儿有一个过滤器,确保ctrl+alt+f1在锁屏情况下仍然能够工作。另一个过滤器用来处理全局快捷键,一个将事件传递给特效系统,比如窗口轮转。

在调试终端中,一个输入事件过滤器显示被按下的键

最后一个过滤器是我们的转发过滤器。这个过滤器的任务是转发事件到窗口。它将事件从当前活动的Wayland平面,传递到KWayland::Server。

获得键盘输入焦点的Wayland表面

Wayland服务器需要获取了键盘焦点的平面。在获取了键盘焦点的情况下,KWin相比而言微不足道。KWin有一个叫活动窗口的概念。在转发事件之前,KWin会检查哪个是键盘焦点窗口。如果有一个活动窗口,则该窗口平面被标记为KWayland::Server中的键盘焦点平面。

我们的KWayland::Server库关注发送丢失键盘焦点和获取键盘焦点事件到窗口,所以KWin不需要关注这些。这是我们有一个KWayland::Server抽象层的优势——和混成器无关的一切都在库中被处理了。

Wayland中键盘事件的处理

之前提到的转发过滤器更新键盘平面,并且将当前键盘事件发送到Wayland客户端。对于所有在keysymbol中的处理,都不需要了。key code已经送到了客户端。

客户端从回调中得到键盘事件,现在也将其送到xkbcommon。在Wayland中,keymap从服务端送到客户端,以便服务端和客户端有同样的keymap。客户端现在将key code转换成key symbol,和之前KWin做的一样。

接下来的事件处理在客户端完成。比如在QT中,这一步会产生QKeyEvent,然后送到当前输入焦点的widget。

重复输入键

键盘输入也有一些特殊的模式:重复键。当一些键被按下,产生重复的键输入。KWin使用来自键盘模块的配置来决定什么时候、什么频率来产生重复的按键。一个重复的键不会被转发到KWayland客户端。而是KWin通过Wayland键盘协议告诉键重复的设定,而不是被客户端直接处理。

不幸的是,QT中这个是不能工作的,使用的是硬编码。所以当前在Plasma Wayland的会话中,根据使用的GUI库不同,对重复键的支持很破碎。如果运行在Wayland上的话,KWin支持是正常的,X11程序是对的,GTK程序是对的,QT程序是错的。


如果你想支持我们[作者]的工作,请考虑捐助

ssh卡在debug1: SSH2_MSG_KEXINIT sent的解决办法

在公司通过kerberos登录ssh,完全没有问题。但是在家里通过l2tp连接vpn后,就无法登录了。

通过ssh -v查看日志,发现卡在debug1: SSH2_MSG_KEXINIT sent这一步。

查了下,发现是因为mtu设置太大


但是由于系统的网络是NetworkManager管理的,如果需要自动设置mtu,connection的配置中并没有vpn对应的mtu设置。后来,看了有人使用dispatcher脚本来设置。

创建/etc/NetworkManager/dispatcher.d/vpn-up文件:

#!/bin/sh

if [ "$2" = "vpn-up" ]; then
        ip link set "$1" mtu 1350
fi

然后vpn连接的时候,就会自动设置mtu了。

[译]输入系统如何工作——创建设备

本文是How input works – creating a Device的翻译。

最近,我[作者]在KWin/Wayland输入栈上做了一些工作,比如实现了鼠标手势和鼠标限制协议(pointer constraints protocol),并且想写一些系列博客来描述输入事件是如何从设备传递到应用的。在第一篇博文中,我将关注于创建和配置输入设备,以及与此相关的其他事情。

evdev

Linux内核通过evdev API来产生输入事件。如果你对evdev如何工作感兴趣,我推荐你读一读Peter Hutterer写的优秀的博文。对于我们关注的层面来说,输入事件API太底层了,我们仅仅想用对它的一个抽象。

libinput 和设备文件

对输入事件API的抽象叫做libinput。它允许我们得到通知,不论何时添加、删除输入设备、不论何时产生输入事件。但是别急,我们首先需要打开输入设备,这是我们的第一个挑战。

正常情况下,设备文件不能被用户读取。这有好的一面,否则每个程序都能够读取所有的键盘事件。这种情况下,键盘记录器太容易实现了。

但是如果KWin以普通用户的方式运行,普通用户又无法读取设备文件,那KWin如何获取输入?为了让KWin获取输入,我们需要特殊的支持。libinput就是为这种情况准备的,它自己不会尝试打开文件,它会使用用户提供的open_restricted函数。KWin就是这么干的,并将打开文件的任务交给了logind。logind允许一个进程控制当前登录会话。并且这个登录会话的控制进程可以打开一些设备文件。所以KWin和logind的dbus API交互,成为登录会话的控制进程,通过logind的API打开设备文件,并将其传递回libinput。

这也是为什么对于整个Wayland会话,KWin在运行时依赖logind的DBus接口。请注意,这并不意味着你需要使用logind或者sysemd。这仅仅意味着需要一个进程来同logind的DBus接口通讯。

KWin中的设备

现在libinput已经准备好打开设备文件,并且为每个设备触发了LIBINPUT_EVENT_DEVICE_ADDED事件。KWin为每一种设备类型创建了一个小的门面类,来应用设备的配置。KWin支持读取Plasma的鼠标配置模块中的配置选项。并且KWin打开了LED灯,如果设备支持LED灯的话,比如数字锁定灯和大写锁定灯,这也是设备配置过程的一部分。

所有的输入设备都被KWin创建,并且可以在调试终端显示(打开KRunner,输入“KWin”)。KWin从libinput中读取了很多关于设备的信息,并展示在调试终端中。在输入事件选项卡中,每种事件都包含了设备产生该事件的一些信息。

所有的设备也通过DBus暴露出来,和KWin的调试终端信息一样。这意味着可以通过DBus来动态修改配置。不过,KWin在成功应用配置后,会将其保存,以确保你在重启系统、或者重新插拔外部设备后,你的设置能够被恢复。这是一个很重要的特性,用来支持触摸板配置模块。

如果你想支持作者的工作,考虑捐赠给作者,让世界变得更美好!——KDE 2016年年终募款

How to use mysql-connector-python 2.1.5 on Django 1.10?

MySQL Connector/Python currently not available from PyPI

When you want use mysql-connector-python as db backend in Django, the first thing you noticed is that the latest version of mysql-connector-python on PyPI is 2.0.4, but official version is 2.1.5.

The official developer explained this.(But why not host mysql-connector-python on PyPI?!).

so, you can bypass this problem. Add follow line into requirements.txt:

https://dev.mysql.com/get/Downloads/Connector-Python/mysql-connector-python-2.1.5.tar.gz#egg=mysql-connector-python

when you configured Connector/Python Django Backend, and run python manage.py migrate , you will meet error:

DatabaseError: Data truncated for column ‘applied’ at row 1

This is because mysql.connector.django cannot handle datetime with timezone.

You need patch 93c7b38.

when you fix this, you must drop all table, and re-run python manage.py migrate, you will meet another error:

  File "/path/to/venv/lib/python3.5/site-packages/mysql/connector/django/operations.py", line 223, in bulk_insert_sql
    return "VALUES " + ", ".join([items_sql] * num_values)
TypeError: can't multiply sequence by non-int of type 'tuple'

can’t multiply sequence by non-int of type ‘tuple’

This is because bulk_insert_sql ‘s third argument changed from int to list of placeholder rows, since Django 1.9.

You need another patch, patch 8dab00b. (Of cause, we doesn’t drop support of Django 1.6)


Now you can use mysql-connector-python 2.1.5 on Django 1.10, if you meet another problem, post the comment here!

Django的MySQL Driver配置

之前写过一篇文章《[email protected]添加MySQL/MariaDB支持》,现在Django对MySQL的支持已经很好了,现在就说一说最佳实践吧。

PEP 249规定了Python的数据库API。MySQL主要有三种API实现:

  • MySQLdb 是Andy Dustman开发的、使用原生代码/C语言绑定的驱动,它已经开发了数十年。
  • mysqlclient 是MySQLdb的一个支持Python3的fork,并且可以无缝替换调MySQLdb。mysqlclient目前是MySQL在Django下的推荐选择。
  • MySQL Connector/Python 是Oracle写的,纯Python实现的客户端库。

以上所有的驱动都是线程安全的,且提供了连接池。MySQLdb 是唯一一个不支持Python3的。

如果你使用mysqlclient

settings.py中的配置如下:

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', #数据库引擎
        'NAME': 'test',                       #数据库名
        'USER': 'root',                       #用户名
        'PASSWORD': 'root',                   #密码
        'HOST': '',                           #数据库主机,默认为localhost
        'PORT': '',                           #数据库端口,MySQL默认为3306
        'OPTIONS': {
            'autocommit': True,
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

第14行主要是为了防止警告:

(mysql.W002) MySQL Strict Mode is not set for database connection 'default'

当然,要在requirements.txt中添加对mysqlclient的依赖:

mysqlclient==1.3.10

然后运行python manage.py migrate :

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  。。。。。。

如果你使用MySQL Connector/Python

这么长时间了,Oracle官方的connector还是不太好用。

首先,一些补丁需要打:patch 93c7b38, patch 8dab00b要打上。

其次,这个包无法从PyPI安装了,只能从下载链接安装。

如果你要使用MySQL Connector/Python,首先,在requirements.txt中声明依赖:

https://dev.mysql.com/get/Downloads/Connector-Python/mysql-connector-python-2.1.5.tar.gz#egg=mysql-connector-python

其次,在settings.py里面关于数据库的配置如下:

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'mysql.connector.django',   #数据库引擎
        'NAME': 'test',                       #数据库名
        'USER': 'root',                       #用户名
        'PASSWORD': 'root',                   #密码
        'HOST': 'localhost',
        'OPTIONS': {
            'autocommit': True,
        },
    }
}

然后运行python manage.py migrate