Django自学笔记-第三章
内容来源: 极客时间
迭代思维与 MVP 产品规划方法(OOPD)
- MVP:minimum viable product, 最小可用产品
- OOPD:Online & Offline Product Development, 线上线下相结合的产品开发方法
- 内裤原则:MVP 包含了产品的轮廓,核心的功能,让业务可以运转
- 优先线下:能够走线下的,优先走线下流程,让核心的功能先跑起来,快速做用户验证和方案验证
- MVP 的核心:忽略掉一切的细枝末节,做合适的假设和简化,使用最短的时间开发出来
- 迭代思维是最强大的产品思维逻辑,互联网上唯快不破的秘诀
- 优秀的工程师和优秀的产品经理,善于找出产品 MVP 的功能范围
微信 1.0 的 MVP 迭代
- 只有 3 个功能
- 聊天发文本消息
- 发送图片
- 自定义头像
- 没有更改用户昵称的功能
- 产品的目标
- 替换掉短信的免费聊天工具
如何找出产品的 MVP 功能范围?
使用这些问题来帮助确定范围
- 产品的核心目标是什么? 核心用户是谁?核心的场景是什么?
- 产品目标都需要在线上完成或者呈现吗?
- 最小 MVP 产品要做哪些事情,能够达到业务目标?
- 哪些功能不是在用户流程的核心路径上的?
- 做哪些简化,和假设,能够在最短的时间交付产品,并且可以让业务流程跑起来?
用户场景和功能清单:找出必须的功能
- 定义最小可用的面试评估系统
- 哪些是可以线下人肉做的事情
- 可以做出哪些假设来简化产品
| 角色 | 功能 | 是否必须 |
|---|---|---|
| HR | 可以管理职位 | 否 |
| 候选人 | 可以浏览职位列表,详情 | 否 |
| 候选人 | 可以在线投递简历 | 否 |
| HR | 查看候选人投递的简历,审核简历 | 否 |
| HR | 导入候选人 | 否 |
| HR | 添加,修改候选人,查看候选人列表 | 是 |
| 管理员 | 可以添加面试官 | 否 |
| 面试官 | 可以进行一面,二面;HR可以进行终面 | 是 |
| 管理员 | 能够管理HR,面试官的角色 | 否 |
| HR/面试官 | HR和面试官只能看到有权限的内容 | 否 |
核心目标:
- 提高面试效率
- 使面试结果可以跟踪, 追溯
根据以上核心目标, 其他功能都不属于第一版MVP内容, 因此仅保留与面试过程相关内容即可
企业级数据库设计十个原则
其中:
3个基础原则与3个完备性原则所有的企业级数据库均必须遵守,
扩展性原则可选
3个基础原则
- 结构清晰:表名、字段命名没有歧义,能一眼看懂
- 唯一职责:一表一用,领域定义清晰,不存储无关信息,相关数据在一张表中
- 主键原则:设计不带物理意义的主键;有唯一约束,确保幂等
4个扩展性原则(影响系统的性能和容量)
- 长短分离:可以扩展,长文本独立存储;有合适的容量设计
- 冷热分离:当前数据与历史数据分离
- 索引完备:有合适索引方便查询
- 不使用关联查询:不使用一切的 SQL Join 操作,不做 2 个表或者更多表的关联查询
3个完备性原则
- 完整性:保证数据的准确性和完整性,重要的内容都有记录
- 可追溯:可追溯创建时间,修改时间,可以逻辑删除
- 一致性原则:数据之间保持一致,尽可能避免同样的数据存储在不同表中
第一个迭代
创建面试应用
使用manage.py创建一个新的应用
1 | ./manage.py startapp interview |
增加自定义模块
修改recuritment/interview/models.py文件,
添加额外模块信息
1 | from django.db import models |
字段说明
| 字段类型 | 字段名称 | 说明 |
|---|---|---|
| EmailField | 邮箱地址类型 | 用于显示邮件地址类型 |
| DecimalField | 十进制数字类型 | 可以设置精度的十进制数字 |
注册应用
修改recuritment/interview/admin.py文件,
注册当前的应用
1 | from django.contrib import admin |
注册应用到项目
同样的, 修改recuritment/settings.py文件,
添加将interview注册到项目中
1 | ... |
此时访问页面, 会发现报错
同步数据库
仍旧需要执行数据库同步操作
1 | ./manage.py makemigrations |
尝试增加应聘者
发现目前的应用有需要优化的点:
1. 整体表单条目数量过多
1. 需要对多个面试情况进行分区展示处理
通过对指定字段拼接成元组的方式, 可以实现字段分组, 见修改后的模型
1 | from django.contrib import admin |
展示效果如下:
参考网页
使用 Model 模型
https://developer.mozilla.org/zh-CN/docs/Learn/Serverside/Django/Models
https://docs.djangoproject.com/en/3.1/topics/db/models/
使用 Admin 管理类
https://developer.mozilla.org/zh-CN/docs/learn/Serverside/Django/%E7%AE%A1%E7%90%86%E7%AB%99%E7%82%B9
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/
第二个迭代
实现候选人批量导入
- 怎么样实现一个数据导入的功能最简洁
- 开发一个自定义的 Web 页面,让用户能够上传 excel/csv 文件
- 开发一个命令行工具,读取 excel/csv,再访问数据库写入 DB
- 从数据库的客户端,比如 MySQL 的客户端里面导入数据
- Django 框架已经考虑到(需要使用到命令行的场景)
- 使用自定义的
django management命令来导入数据 - 应用下面创建
management/commands目录 - commands 目录下添加脚本,创建类,继承自 BaseCommand,实现命令行逻辑
- 使用自定义的
在interview项目创建文件management/commands/import_candidates.py,
并实现读取CSV文件功能脚本
1 | #!/usr/bin/env python3 |
使用命令测试脚本是否可用
1 | ./manage.py import_candidates --path ./candidates.csv |
执行完成后, 访问页面查看效果
第三个迭代
实现对候选人信息的快速筛选
- 能够按照名字、手机号码、学校来查询候选人信息
- 能够按照初试结果,复试结果,HR复试结果,面试官来筛选;能按照复试结果来排序
增加搜索功能
修改interview/admin.py中的CandidateAdmin类,
增加如下字段
1 | # 增加搜索字段 |
实现效果
可以对各项设置的搜索项进行模糊搜索功能
增加筛选功能
修改interview/admin.py中的CandidateAdmin类,
增加如下字段
1 | # 增加筛选字段 |
实现效果
可以对各项设置的过滤项进行过滤功能
增加排序功能
修改interview/admin.py中的CandidateAdmin类,
增加如下字段
1 | # 增加排序字段 |
实现效果
企业域账号集成
概念
什么是目录服务 Directory Service ?
目录服务对于网络的作用就像白页对电话系统的作用一样。目录服务将有关现实世界中的事物(如人、计算机、打印机等等)的信息存储为具有描述性属性的对象。人们可以使用该服务按名称查找对象或者像使用黄页一样,可使用它们查找服务。
使用目录服务的好处?
- 可以直接使用域账号登陆
- 不用手工添加账号,维护独立密码
- 可以集成 OpenLDAP/ActiveDirecotry
以 Open LDAP 为例
- DN: 目录服务中的一个唯一的对象 CN=David,OU=Shanghai,DC=ihopeit,DC=com
使用Docker临时创建测试LDAP服务
1 | COMPANY="goldwind" |
使用下面创建的LDIF文件可导入几个测试用户
1 | # LDIF Export for dc=goldwind,dc=com |
其中Tom Yang的默认密码为123,
Sandy Guo的默认密码为456
设置Django支持LDAP认证
使用pip安装ldap包
1 | pip install django-python3-ldap |
修改recuritment/settings.py文件,
添加django-python3-ldap应用, 并配置该应用
1 | ... |
登录前系统用户
尝试使用域账号登录
图中因为中文缘故无法正确展示报错信息, 修改语言为英文后可见报错
在后台可以看到, 域账户并非员工账号
选择刚才添加的域账号, 勾选Staff status后保存
我这里因为使用了空格, 因此保存会报错
需要修改用户名为Tom_Yang后方可保存,
并且需要同步修改LDAP中的CN信息
再次尝试登录, 后台系统可以登录
批量添加用户
首先先对ldap用户进行同步操作
1 | ./manage.py ldap_sync_users |
此时登录后台可观察到用户已同步
设置角色群组
添加面试官群组interviewer
添加HR群组hr
为导入的用户增加群组
注意: 用户需勾选工作人员状态, 并附加群组, 否则无法登录
此时使用添加的用户进行登录, 发现权限已生效
其中Tom属于interviewer群组,
拥有查看候选人和修改候选人的权限,
而Sandy属于hr群组,
拥有候选人的增删改查权限及发布职位的增删改查权限
第四个迭代
增加导出Action
修改interview/admin.py文件, 增加如下自定义方法
1 | import csv |
并修改CandidateAdmin类, 添加如下属性
1 | ... |
刷新后台管理页面, 并进入候选人应用, 发现已支持导出操作
打开csv文件, 数据正常
导出功能汉化
设置自定义Action的属性以支持汉化说明
1 | def export_as_csv(model_admin, request, query_set): ... |
此时重新刷新页面, 导出操作已汉化
增加日志功能
定义项目日志格式字典
修改recuritment/settings.py文件, 增加日志字典
1 | ... |
重新使用ldap认证方式登录系统, 发现日志输出
在自定义Action中使用日志
修改interview/admin.py文件, 引入logging包,
并定义logger记录器
1 | import logging |
进入Web页面, 尝试导出数据, 发现日志系统已记录
配置分离
抽离默认环境配置
在
recuritment项目目录下, 创建Python包settings移动
recuritment/recuritment/settings.py文件并重命名至recuritment/settings/base.py修改
recuritment/settings/base.py, 隐藏默认配置1
2
3
4
5
6
7
8...
DEBUG = False
ALLOWED_HOSTS = ['127.0.0.1']
...
LDAP_AUTH_CONNECTION_USERNAME = None
LDAP_AUTH_CONNECTION_PASSWORD = None
...新建本地配置
recuritment/settings/local.py, 并覆盖base中定义的内容1
2
3
4
5
6
7from .base import *
ALLOWED_HOSTS = ['127.0.0.1', '0.0.0.0']
LDAP_AUTH_CONNECTION_USERNAME = 'admin'
LDAP_AUTH_CONNECTION_PASSWORD = '9ol.8ik,'
DEBUG = True在本地
.gitignore文件中, 添加本地配置忽略1
2
3...
settings/local.py新建生产环境配置
recuritment/settings/production.py, 并覆盖base中定义的内容1
2
3
4
5
6
7
8from .base import *
ALLOWED_HOSTS = ['127.0.0.1']
LDAP_AUTH_URL = "ldap://127.0.0.1:389"
LDAP_AUTH_CONNECTION_USERNAME = 'admin'
LDAP_AUTH_CONNECTION_PASSWORD = '9ol.8ik,'
DEBUG = False## 依据不同环境使用不同配置
默认情况使用
base.py中定义的内容1
python ./manage.py runserver 0.0.0.0:9999
通过指定配置参数
--settings, 可切换不同环境1
2
3
4# 使用本地配置
python ./manage.py runserver 0.0.0.0:9999 --settings=settings.local
# 使用生产环境配置
python ./manage.py runserver 0.0.0.0:9999 --settings=settings.production
完善产品细节
视频链接: https://time.geekbang.org/course/detail/100061901-300874
修改页面标题
修改recruitment/recruitment/urls.py, 增加页面标题
1 | from django.utils.translation import gettext |
刷新页面, 标题修改已生效
增加面试官打分提示信息
修改recruitment/interview/models.py,
增加打分提示信息
1 | ... |
刷新页面, 可以看到打分系统增加了提示信息
修改面试官为下拉选择
修改recruitment/interview/models.py, 增加外键引用
1 | from django.contrib.auth.models import User |
替换所有recruitment/interview/admin.py文件中对原有字段的引用
1 | first_interviewer -> first_interviewer_user |
执行数据库创建迁移并迁移
1 | ./manage.py makemigrations |
刷新页面, 可以看到面试官选择为下拉列表
限制面试官修改权限
目标是限制面试官用户, 无权修改面试官信息, 只能填写相关字段
修改recruitment/interview/admin.py, 重构父类函数
1 | class CandidateAdmin(admin.ModelAdmin): |
使用面试官Tom_Yang账号登录, 验证无法修改面试官信息
增加列表页编辑面试官功能
因候选人数量很多, HR不方便逐个进入详情页变更面试官信息, 希望在列表页提供直接修改功能
修改recruitment/interview/admin.py, 重构父类函数
1 | class CandidateAdmin(admin.ModelAdmin): |
使用HR用户登录, 可以批量修改面试官信息
使用面试官用户登录, 无法修改面试官信息