Django 后端学习路线
推荐从上往下看。
- 官方快速安装指南(3.1 版本),安装的教程
- 官方中文教程(3.1 版本),开发的教程
- MDN 上的 Django 教程,和上面的教程有重叠,推荐只看会话和用户认证部分
- Django REST Framework,这是一个基于 Django 的 RESTful 后端框架,为常见 RESTful 操作提供了模板,大大降低 REST API 开发量
Django 官方教程 关键步骤
本小节记录了 官方中文教程(3.1 版本) 中的关键步骤。
1. 创建项目、项目和一个视图
- 安装:
pip install Django
- 验证安装:
python -m django --version
- 创建并初始化项目文件夹:
django-admin startproject <projectname>
- 即时预览:在
<projectname>
目录下python manage.py runserver [port]
- 创建应用:
python manage.py startapp <appname>
- 编写视图:
1 | # polls/views.py |
- 在应用中添加写好的视图:
1 | # polls/urls.py |
- 在站点中添加应用的视图:
1 | # mysite/urls.py |
2. 数据库使用、管理员
2.1 配置数据库
- 安装 mysqlclient:
pip install mysqlclient
- 修改项目配置文件:
1 | # mysite/settings.py |
2.2 创建模型并迁移至数据库
一个 Django 模型对于一个 SQL 数据表。
- 创建模型:
1 | # polls/models.py |
- 激活模型:
1 | # mysite/settings.py |
- 将模型更改写入数据库:
- 根据类的更改,生成一个
迁移
(一个存储在<app_lable>/migrations
下的 py 文件,存储了变化):python manage.py makemigrations [app_label]
(文档) - 将一个
迁移
应用到数据库,并迁移数据:python manage.py migrate [app_label] [migration_name]
(文档) - 查看一个
迁移
将对数据库造成的影响:python manage.py sqlmigrate <app_label> <migration_name>
(文档) - 一般来说,类变更以后,需要:
python manage.py makemigrations && python manage.py migrate
- 第一次部署的时候,需要
python manage.py makemigrations <app1> <app2> <...appn> && python manage.py migrate
- 根据类的更改,生成一个
对了,migrations
文件夹应当加入 .gitignore
,否则不同开发者的 migrations
就要冲突啦。
2.3 数据库 API
- 进入 Python 命令行:
python manage.py shell
- 使用前先引入类:
from polls.models import Choice, Question
对于一个数据表:
- 一个表的所有元素:
Question.objects.all()
- 以成员筛选记录:
Question.objects.filter(id=1)
- 以
pub_date
成员的year
成员筛选(成员方法同理):pub_date.year
:Question.objects.filter(pub_date__year)
对于一个记录:
- 构造一个新记录:
q = Question(question_text="What's new?", pub_date=timezone.now())
- 将记录插入表:
q.save()
- 查询、修改记录的属性(同理可调用其方法):
q.question_text
- 删除一个记录:
q.delete()
对于一个外键(Choice
存在外键,为 Question
):
- 查询一个 Choice 对应的 Question:
c.qeustion
- 查询一个 Question 对应的 Choice:
q.choice_set.all()
- 为 Question 创建一个 Choice:
q.choice_set.create(choice_text='Not much', votes=0)
2.4 管理员相关
- 创建管理员:
python manage.py createsuperuser
- 管理员登录界面:
http://127.0.0.1:8000/admin/
- 在管理员页面中添加
Question
模型:
1 | # polls/admin.py |
3. 视图和 urls
3.1 添加更多视图,并用参数匹配 url
1 | # /polls/views.py |
1 | # /polls/url.py |
访问 /polls/34
会返回 You're looking at question 34.
3.2 使用 HTML 模板
编写一个 HTML 模板:
1 | <!-- /polls/templates/polls/index.html --> |
再在视图中:加载模板、用数据渲染、然后转为 HTTP Response,三步使用 django.shortcuts.render()
完成
1 | from django.shortcuts import render |
3.3 抛出 404 错误码
1 | from django.http import Http404 |
也可以使用 django.shortcuts.get_object_or_404
。该函数在 object
不存在会 raise Http404()
:
1 | from django.shortcuts import get_object_or_404, render |
也有 get_list_or_404()
函数,工作原理和 get_object_or_404()
一样,除了 get()
函数被换成了 filter()
函数。如果列表为空的话会抛出 Http404
异常。
3.4 使用 name 替代 URL 中的硬编码、为 URL 名称添加命名空间(app_name)
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial03/#removing-hardcoded-urls-in-templates
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial03/#namespacing-url-names
4. 编写一个简单的表单
因为我想用 Django 做纯 REST 后端,所以这部分略。
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial04/
5. 测试
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial05/
关于测试还是值得单独拿一个章节出来的:测试
6. 插入静态文件
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial06/
7. 修改 Admin 页面
https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial07/
如果想要修改某元素对应外键的信息(而不是修改其外键),可以参考 django.contrib.admin.StackedInline
如果想要汉化 Admin 页面,可以参考:https://blog.csdn.net/aaazz47/article/details/78666099
Django 用户认证
Django 用户认证(后端篇)
MDN 教程:https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Django/Authentication
文档:https://docs.djangoproject.com/zh-hans/3.1/topics/auth/default/
- 创建用户:
user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
- 创建超级用户:在命令行中
python manage.py createsuperuser
- 登录:
1 | from django.contrib.auth import authenticate, login |
- 判断用户身份:可以通过
request.user.is_authenticated==False
表示为匿名者;否则request.user
会被设置为User
实例。 - 更改密码:
1 | from django.contrib.auth.models import User |
login_required
装饰器:
1 | from django.contrib.auth.decorators import login_required |
- 登出:
django.contrib.auth.logout(request)
Django 用户认证(前端篇)
Django 的用户认证是用 Session 实现的,和其他的 Session 应该是类似的。但对于零基础前后端开发的我,不清楚这之中究竟发生了什么。于是我简单测试了一下。
在登录成功后,应答的 headers 中就会出现 Set-Cookies
字段:
1 | $ http POST http://127.0.0.1:8000/api/accounts/login/ <<< '{"username":"lyh543@outlook.com", "password":"xxxxxxxx"}' |
前一个 csrftoken
是防止跨站请求的,如果项目是前后端分离的话,就需要进行配置;
后一个 sessionid
就是登录成功后的 sessionid
了。如果我们在下次请求中的 headers 中加入了这个 sessionid
,服务器就能识别到我们。对于 Django 来说,就是 request.user
为登录的这个用户。
对于浏览器、requests.sessions.Session
等,会自动设置 Cookie。下面是利用 requests.sessions.Session
完成登录、查询管理员字段的过程:
1 | In [2]: import requests |
而对于非登录操作、或登录失败,应答中的字段就不会有 Set-Cookies
字段,requests.sessions.Session
也不会设置 Cookies
:
1 | In [2]: import requests |
Django Session 的过期时间也是可以通过修改 SESSION_COOKIE_AGE
来修改的。
使用 JWT 进行身份验证
Django 自带的 Session 对于很多项目已经够用了。如果想要更高级一点的安全验证,如 Json Web Token,可以尝试 Simple JWT 配合 Django REST Framework 食用。文档给的示例代码很详细,有需要也可以仿照源码编写自己的 API。
Django 定时任务
可参考 Django-crontab。
Django REST Framework
这部分就另开一篇博文来写了。
Django 项目部署
诚然,python manage.py runserver 8000
然后将 8000 端口交给 Nginx / Apache / Caddy 反向代理到 80(http) / 443(https),是最简单且最直接的方法。但是,其替代方案有多线程、占用内存小等优势。
Django 的管理命令
startproject
生成了一个最小化的默认 WSGI 配置,你可以按照自己项目的需要去调整这个配置,任何兼容 WSGI 的应用程序服务器都可以直接使用。
而其中一个 WSGI 应用程序服务器的方案,就是使用 Gunicorn。由于细节比较多,各位先不要急着实践,建议先通读这部分,再决定是否采用这种方式还是直接 startproject
。
安装 Gunicorn:
1 | python -m pip install gunicorn |
在项目文件夹下运行:
1 | gunicorn -b "127.0.0.1:8000" <projectname>.wsgi |
其中 <projectname>.wsgi
也是 Python 的模块的表示方法,其表示 ./<projectname>/wsgi.py
这个模块。
可以将执行这条命令的过程写为 Systemd 服务,并实现自动重启等:
1 | # djangoproject.service |
命令的 --access-logfile -
表示将 log 输出在控制台,在 Systemd 中即表示可以通过 systemctl status djangoproject
查询日志。
然后就是将这项服务复制到 /etc/systemd/system/
,然后 enable 和 start 了:
1 | sudo cp ./djangoproject.service /etc/systemd/system/ |
但是!这并没有完成部署。访问 localhost:8000
时,可以看到 Django 有正常响应,但是所有静态文件全部失效,Swagger 文档生成也失效了。
为了解决这个问题,需要配置静态文件。
在 <projectname>/settings.py
中配置以下几个参数
1 | import os |
三个参数的意义如下:
BASE_DIR/static
是开发中静态文件所在文件夹BASE_DIR/.static
是项目生成后静态文件所在文件夹,应当加入.gitignore
/api/static/
是在网页中访问静态文件的路径
整个过程是这样的:
- 开发者将所需的静态文件放入
BASE_DIR/static
- 开发者运行
python3 manage.py collectstatic
,Django 将开发者提供的BASE_DIR/static
文件,和 Swagger 等 APP 提供的静态文件,一并复制进BASE_DIR/.static
- 用户在浏览器中访问
/api/static/
路径,表示用户想访问的文件夹是BASE_DIR/.static
所以还需要进行以下两步:
- 运行
python3 manage.py collectstatic
- 通过 Nginx / Apache / Caddy 等将静态文件提供给用户
Gunicorn 提供了一个 Nginx.conf 配置模板,我也提供一份 Caddy 的配置模板:
1 | { |
需要注意的是,这种配置的前提是所有 REST API 放在了 /api/
下,这种方法使用的 <projectname>/urls.py
如下:
1 | api_urlpatterns = [ |
项目开源地址
上面提到的项目开源在 GitHub。