# 0x00 前言

本文是 Django 全栈开发教程的第一篇,上一篇是第零篇,目录会随时更新,地址在这里 2018 年不容错过的 Django 全栈项目 https://zhuanlan.zhihu.com/p/33903527

为什么是第零篇,因为程序员从零计数呀。笑~~

本文需要完成两件事情:

  • 配置基本的开发环境
  • 让代码先运行一下

如果你使用的 macOS, 那么可以跟着下文一步一步走。如果是 linux/window 用户,可能稍微需要在配置环境上多花点时间。

本文默认你至少会在 iTerm2 下面使用基本的 bash 命令与 git , 如果使用的 ohmyzsh 就更好了。 建议先参考请查看我之前的文章里面的配置环境 如何优雅地使用 macOS https://zhuanlan.zhihu.com/p/29892969

# 0x01 Python 开发环境配置

本小节的目的就是配置好基本的 python 开发环境

使用了神器 pyenv

BTW: 为什么不直接用 pipenv ? 因为网络不通畅,如若不然,pipenv 比 pyenv 更适合用来做 python 依赖包管理。

# 新开终端
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc

# 接着另开终端
# 不喜写兼容代码,所有代码均向 3.5+ 靠拢
v=3.5.2|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v
v=3.6.0|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v
v=2.7.11|wget http://mirrors.sohu.com/python/$v/Python-$v.tar.xz -P ~/.pyenv/cache/;pyenv install $v

# 设置 Global Python 为 2.7.11, 备注:尽量不要把 Py3 设置为全局,否则由于 Homebrew 本身有一些依赖是依赖于 Py2 的,这样容易出现一些奇怪的问题。
pyenv global 2.7.11
pip install -i https://pypi.doubanio.com/simple requests
# 下面这个是用于安装基本的代码补全功能
pip install -i https://pypi.doubanio.com/simple --upgrade "jedi>=0.9.0" "json-rpc>=1.8.1" "service_factory>=0.1.5" flake8 pytest autoflake hy

# 创建最常用 Py3 虚拟环境
pyenv virtualenv 3.5.2 py3-daily
pyenv activate py3-daily
pip install -i https://pypi.doubanio.com/simple requests
pip install -i https://pypi.doubanio.com/simple beatutifulsoup4
pip install -i https://pypi.doubanio.com/simple ipython[notebook]
pip install -i https://pypi.doubanio.com/simple jupyter
# 下面这个是用于安装基本的代码补全功能
pip install -i https://pypi.doubanio.com/simple --upgrade "jedi>=0.9.0" "json-rpc>=1.8.1" "service_factory>=0.1.5" flake8 pytest autoflake hy

好,Python 环境就安装完毕了。

# 0x02 JavaScript 开发环境配置

本小节的目的就是配置好基本的 JS 开发环境,但估计 JSer 看了本小节依旧可以在配置上少一些麻烦。

JS 可以前后端通吃,社区生态很丰富。ES6 之后从 python 和 ruby 里面借鉴了不少语法糖。现在写起来还是比较愉悦的。

JavaScript 不管开发前端应用还是后端应用,都需要安装 node 环境。

# 先安装 nvm
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
# 新开终端
nvm install 8
nvm use 8
nvm alias default 8

npm install cnpm
cnpm install yarn -g
# 设置镜像
yarn config set registry https://registry.npm.taobao.org

编辑 ~/.npmrc 配置文件,输入下文再配置各种奇奇怪怪的镜像地址。

registry=https://registry.npm.taobao.org/
chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver
disturl=https://npm.taobao.org/dist
operadriver_cdnurl=http://cdn.npm.taobao.org/dist/operadriver
phantomjs_cdnurl=http://cdn.npm.taobao.org/dist/phantomjs
fse_binary_host_mirror=https://npm.taobao.org/mirrors/fsevents
sass_binary_site=http://cdn.npm.taobao.org/dist/node-sass
electron_mirror=http://cdn.npm.taobao.org/dist/electron/

配置完毕

# 0x03 Docker 安装与配置

本小节主要解决一个最蛋疼的问题,就是网络问题

下载并安装 docker for mac 地址如下 https://docs.docker.com/docker-for-mac/install/

# 安装成功后运行命令
docker run hello-world

如果一切正常,则会显示如下

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:083de497cff944f969d8499ab94f07134c50bcf5e6b9559b27182d3fa80ce3f7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

好,配置到这里。

你以为你已经配置好了,还先别激动,网络问题还没解决呢。小的镜像可以直接从 Docker 上直接拖下来,几百兆的镜像可就没这么容易了。

这里我们使用了阿里云的 Docker 容器镜像。

登录阿里云,到控制台,找到容器镜像服务,镜像加速器,

如下图:

右键点击桌面顶栏的 docker 图标,选择 Preferences ,在 Daemon 标签(Docker 17.03 之前版本为 Advanced 标签)下的 Registry mirrors 列表中将 https://your-url.mirror.aliyuncs.com 加到"registry-mirrors"的数组里,点击 Apply & Restart 按钮,等待 Docker 重启并应用配置的镜像加速器。

Docker 配置完毕。

# 0x04 项目试运行

运行项目之前,保持你我的工作环境基本一致

  • 创建一些必须的目录
  • clone 项目
mkdir -p ~/Codes/YaBlog/DockerVolume/YaDjangoBlog/PostgreSQL/data
mkdir -p ~/Codes/YaBlog/DockerVolume/YaDjangoBlog/Redis/data
mkdir -p ~/Codes/YaBlog/DockerVolume/YaDjangoBlog/Backups
cd ~/Codes/YaBlog/
git clone git@github.com:twocucao/YaVueBlog.git
git clone git@github.com:twocucao/YaDjangoBlog.git

克隆下来项目之后还需要稍微折腾一下(没办法,CURD 开发 = 折腾折腾折腾 + 搬砖搬砖搬砖)

  • 运行 Vue 开发环境
  • 运行 Docker 化的 django 环境
# 新开一个终端 用于运行 Vue 应用
# 前端环境不放在 Docker 环境中。(因为开发环境没必要,生产环境才需要)
cd ~/Codes/YaBlog/YaVueBlog/ && yarn && cd -
cd ~/Codes/YaBlog/YaVueBlog/packages/theme-future/ && yarn && cd -
cd ~/Codes/YaBlog/YaVueBlog/
npm run build:theme
npm run dev
# 新开一个终端
cd ~/Codes/YaBlog/YaDjangoBlog/
make

看到下图,包含所有的命令。

这是我用 Makefile 编写的一系列命令,方便我在开发过程将主要的精力花在业务逻辑上而不是花时间在强记大量的琐碎的命令。

cd ~/Codes/YaBlog/YaDjangoBlog/
make build-all
# 等待运行后端所有组件

然后,读者可以先去泡杯咖啡点个外卖吃个饭之类的。等待构建完毕。

需要注意的是,务必配置好 docker 镜像加速地址,否则根据国内情况,你可能需要多去泡几杯咖啡,多吃几顿饭。

好,接下来我们运行后端程序,首次运行需要花费不少时间

cd ~/Codes/YaBlog/YaDjangoBlog/
make django-just-up

运行之后,终端结果如下:

可以发现,服务已经都开始启动了。

但不要冲动,先等等,因为一次开了如下的服务:

  • postgres
  • redis
  • elasticsearch
  • mailhog
  • django
  • celerybeat
  • celeryworker
  • celeryflower

需要多等会儿时间到各个服务运行正常。直到出现下图:

这意味着基本上所有的程序都运行正常了。如果有服务挂掉,欢迎到 github 的 issue 上提一下。

# 接着再新开一个终端 用于导入基础数据
cd ~/Codes/YaBlog/YaDjangoBlog/
make django-import-articles

好,那么,我们来验证一下如下几个地址:

如果一切正常,则所有的截图应该如下

# 0x05 Tmux 和 Tmuxinator

我们在上文中可以发现有个极其蛋疼菊紧的问题。

当我们运行 make django-just-up 这个命令的时候,所有服务运行的同时,所有的标准输入都打印到一个终端。

这个和我们日常开发不太相同

  1. 在 django 开发的时候,我们运行 runserver, 肯定是只想在那个终端里看到 runserver 的运行情况。而不是 Redis,Elasticsearch,PGsql 之类的 log。
  2. 并且,django 的热加载会有些小问题,有些错误只能 ctrl+c 关掉 runserver, 然后重启。但当我们想 ctrl+c 关掉 runserver 的时候,却把所有的的服务都关掉了。

解决方式也简单:

对于暂时不想在开发时看到日志的服务,干脆直接放后台运行,执行我封装的命令 make django-before-up 把部分服务直接放在后台里,然后再开四个终端,运行下面的命令。

  • make django-runserver # 运行 runserver , 并只把该容器的 log 打印出来。下面三者同上。
  • make django-celerybeat
  • make django-celeryworker
  • make django-celeryflower

显然还是很麻烦,我这种懒人可是能少写几行代码就少些几行代码的。

那么我们还可以更省事(懒一些)么?

我之前写了一篇简单的 tmux 与 Tmuxinator 教程 https://zhuanlan.zhihu.com/p/33369297 , 具体配置步骤参考文中即可。

配置好 Tmuxinator 之后

# 先软连接一下
ln -svf ~/Codes/YaBlog/YaDjangoBlog/yadjangoblog.yml ~/.tmuxinator/yadjangoblog.yml

当我需要运行的所有服务的时候,我只需要

tmuxinator start yadjangoblog

就可以开启所有命令。

yadjangoblog.yml 的内容如下

windows:
  - "前端-页面开发":
      root: ~/Codes/YaBlog/YaVueBlog/
      layout: main-vertical
      panes:
        - "前端页面 DEV":
          - "npm run dev"
  - "前端-CSS 与字体文件":
      root: ~/Codes/YaBlog/YaVueBlog/
      layout: main-vertical
      panes:
        - "npm run dev:theme"
        - "npm run dev:iconfont"
  - "后端-Django 及其服务":
      root: ~/Codes/YaBlog/YaDjangoBlog/
      layout: main-vertical
      panes:
        - "make django-before-up && make django-runserver"
  - "后端-数据库相关":
      layout: main-vertical
      root: ~/Codes/YaBlog/YaDjangoBlog/
      panes:
        - "sleep 20 && make dbshell"
        - "sleep 20 && make shell"
  - "后端-Celery":
      layout: main-vertical
      root: ~/Codes/YaBlog/YaDjangoBlog/
      panes:
        - "sleep 20 && make django-celerybeat"
        - "sleep 20 && make django-celeryworker"

# 0x06 PyCharm 基本设置

大家应该都用 PyCharm 进行开发了吧。 如果是的话,不看本小节可能会让你栽个跟头

# 这步是给 pycharm 打开代码做准备
pyenv activate py3-daily
pip install -i https://pypi.doubanio.com/simple -r requirements/local.txt

务必完成下面两个步骤

  1. 在 Preferences -> project -> interpreter 选择对应的 py3-daily 虚拟环境。
  2. 在侧边栏把 yadjangoblog , 注意小写的。右键标记为 sources root

这样的标记相当于告诉 PyCharm , 这个项目的 PYTHONPATH 是 yadjangoblog/ , 否则使用 PyCharm 导入 AModel 会自动导入 from yadjangoblog.yaadmin.models from AModel 而不是 from yaadmin.models import AModel , 这会导致程序运行错误。

PS: 包括后面跑单元测试的时候,均手动设置了 PYTHONPATH 变量。

# 0x07 开发流程

本小节,从笔者开机开始,回顾一下环境配置好之后,笔者是如何进入开发状态的:

  1. 开机。输入密码进入桌面。
  2. 打开 Iterm, 运行 tmuxinator start yadjangoblog 开启项目。打开 PyCharm 和 WebStorm
  3. 开发
  • 在 WebStorm 中写写前端代码,在 http://localhost:8080 和 tmux 里的第一个 window 查看状态
  • 在 PyCharm 中写写后端代码,在第三个 window 查看 runserver 状态,在第四个 window 的两个 Panel 运行 python manage.py 相关命令。
  • 在 Chrome Elasticsearch Head 扩展里调试 Elasticsearch 语法
  • http://localhost:8000/api/your-api-path 里调试前后端 API
  • http://localhost:5555 通过 flower 查看相关
  • 当然,你也可以新开一个终端里面,执行 make 查看相关还可以执行哪些命令。

那么,具体执行这些命令背后究竟发生了什么?

  • 数十服务为何突然启动
  • 数百个任务为何半夜消失
  • 正常运行的服务为何屡屡崩溃
  • 这一切的背后!是工程师的人性扭曲还是码畜的道德沦丧?是内存的爆发还是处理器的无奈?
  • 敬请关注本专栏 『MG 的编程小屋』或者 Github 频道,让我们跟随教程走进全干工程师的代码世界。

不好意思,顺手打了个硬广,防止别人把我的文章砍头去尾直接扒过去。

# 0xEE. 参考链接

还犹豫啥,点赞后,快上车吧


ChangeLog:

  • 2018-02-22 重修文字