网站建站建设哪家好,购物商城图片,长春网站建设价格,找人做一下网站大概多少钱前言 首先我们看一下产品的需求背景#xff0c;这个产品为了解决招聘面试的过程中#xff0c;线下面试管理效率低#xff0c;面试过程和结果不方便跟踪的痛点 招聘管理的系统几乎是每一家中小公司都需要的产品 我们以校园招聘的面试为例子来做 MVP 产品迭代 首先我们来看一下… 前言 首先我们看一下产品的需求背景这个产品为了解决招聘面试的过程中线下面试管理效率低面试过程和结果不方便跟踪的痛点 招聘管理的系统几乎是每一家中小公司都需要的产品 我们以校园招聘的面试为例子来做 MVP 产品迭代 首先我们来看一下线下的面试流程线下面试流程分成三个步骤 第一个步骤hr 发出面试评估表到一面面试官 这个评估表是word格式的模板hr 通过邮箱发出来到面试官然后一面面试官登录到邮箱下载word模板为每个学生拷贝一份模板文件使用学生的名字来重命名面试评估表在评估表里面录入学生的名字学校电话学历等等 第二个步骤进行第一轮面试由一面的面试官来面试 每面完一个候选人面试官把面试的结论填写到word格式的评估表中一名面试官在面完一批学生之后批量把 word 格式的评估表发送给hrhr查收下载评估表汇总结果到 excel然后发送到技术二面的面试官做复试通知二面面试官继续做二面 第三个步骤二面面试官查收并下载 word 格式的评估记录开始二面 二面结束后同样的把面试结论追加到 word 格式的面试评估表中然后再邮件通知hr哪些候选人通过了二面接下来hr继续重复前面的操作做第三轮面试 最后用Excel汇总哪些人过了三面需要通知候选人已经被录取 面试评估表里面有候选人的基础信息包括姓名、手机号、应聘职位、毕业院校专业笔试的成绩综合能力测评的成绩
也有一面的初始成绩这一轮评估候选人的学习能力和专业能力
然后还有第二轮复试这一轮评估候选人的追求卓越的能力沟通能力和抗压能力等等 以及最终的 hr 复试hr 复试会评估软性的数字包括责任心、沟通能力、逻辑思维给出最终复试的结论分成4个等级最后择优录取 MVP 产品迭代思想 看起来面试流程蛮复杂的要能够管理候选人有不同的角色需要录入不同内容还要根据状态来判断要不要继续后续面试这么多的功能怎么样能够在一天之内交付可以使用的面试招聘系统 这个就需要使用到产品的迭代思维我们一起来学习迭代的思维一起思考怎么样做 MVP 产品的迭代划分 MVP 包含了产品的轮廓核心的功能能够让业务运转起来的最小功能子集这个版本我们可以叫它内裤版本 所以如果我们规划一个版本开发半年或者一年以上交付一个大而全的产品往往到最后开发出来的都不是用户想要的 同时经过了这么长的时间用户市场需求都已经变化了很多我们还在原地踏步 抱着最初认为正确的产品方案在开发所以长迭代非常可怕尽量把你的迭代周期控制在周的单位甚至是天或者小时为单位 MVP 版本开发出来之后再开始下一个迭代继续下一个 MVP 版本同样是找出对于当前版本的需求来说最核心最重要的功能放在迭代交付然后再交付下一个迭代这个是产品的迭代思维迭代思维是最强大的产品思维逻辑也是互联网唯快不破的秘密 MVP 迭代思想应用 接下来我们一起来看看怎么样把 MVP 迭代的思想应用到我们的招聘面试的系统里面来 我们先来看一下产品的用户场景和功能有哪些 我们把产品 MVP 迭代的思维应用到了我们面试招聘的系统里面来帮我们找出系统里面最核心的两个功能 一个功能是能够维护候选人的信息 另外一个功能是能够去做面试评估去反馈在系统里面录入面试评估的结论 数据库设计原则 现在对我们的系统进行建模并且讲解企业级数据库设计的10个原则 数据建模图如下 我们来讲企业级数据库设计的10个原则 我们将创建面试评估的应用然后创建数据库模型创建数据库模型的时候记得要遵循这些设计原则 创建 interview 应用 实现候选人面试评估表的增删改功能并且按照页面分组来展示不同的内容如候选人基础信息一面二面的面试结果HR 的面试结果 我们可以使用 pycharm 上面菜单栏中 Tools 里的 Run manage.py task这样就不用每次都输入前面的命令了 输入命令 startapp interview 创建完应用后打开 models.py 文件开始编写数据建模代码 from django.db import models# 第一论面试结果
FIRST_INTERVIEW_RESULT_TYPE ((建议复试,建议复试),(待定,待定),(放弃,放弃))# 复试面试建议
INTERVIEW_RESULT_TYPE ((建议录用,建议录用),(待定,待定),(放弃,放弃))# 候选人学历
DEGREE_TYPE ((本科,本科),(硕士,硕士),(博士,博士))# HR终面结论
HR_SCORE_TYPE ((S,S),(A,A),(B,B),(C,C))class Candidate(models.Model):# 基础信息userid models.IntegerField(uniqueTrue, blankTrue, nullTrue, verbose_name应聘者ID)username models.CharField(max_length135, verbose_name姓名)city models.CharField(max_length135, verbose_name城市)phone models.CharField(max_length135, verbose_name手机号码)email models.EmailField(max_length135, blankTrue, verbose_name邮箱)apply_position models.CharField(max_length135, blankTrue, verbose_name应聘职位)born_address models.CharField(max_length135, blankTrue, verbose_name生源地)gender models.CharField(max_length135, blankTrue, verbose_name性别)candidate_remark models.CharField(max_length135, blankTrue, verbose_name候选人信息备注)# 学校与学历信息bachelor_school models.CharField(max_length135, blankTrue, verbose_name 本科学校)master_school models.CharField(max_length135, blankTrue, verbose_name研究生学校)doctor_school models.CharField(max_length135, blankTrue, verbose_name博士生学校)major models.CharField(max_length135, blankTrue, verbose_name专业)degree models.CharField(max_length135, choicesDEGREE_TYPE, blankTrue, verbose_name学历)# 综合能力测评成绩笔试测评成绩test_score_of_general_ability models.DecimalField(decimal_places1,nullTrue,max_digits3,blankTrue,verbose_name综合能力测评成绩)paper_score models.DecimalField(decimal_places1, nullTrue, max_digits3, blankTrue, verbose_name笔试成绩)# 第一轮面试记录first_score models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue, verbose_name初始分)first_learning_ability models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue, verbose_name学习能力得分)first_professional_competency models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue, verbose_name专业能力得分)first_advantage models.TextField(max_length1024, blankTrue, verbose_name优势)first_disadvantage models.TextField(max_length1024, blankTrue, verbose_name顾虑和不足)first_result models.CharField(max_length256, choicesFIRST_INTERVIEW_RESULT_TYPE, blankTrue,verbose_name初试结果)first_recommend_position models.CharField(max_length256, blankTrue, verbose_name推荐部门)first_interviewer models.CharField(max_length256, blankTrue, verbose_name初试面试官)first_remark models.CharField(max_length135, blankTrue, verbose_name初试备注)# 第二轮面试记录second_score models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue, verbose_name专业复试得分)second_learning_ability models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue,verbose_name学习能力得分)second_professional_competency models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue,verbose_name专业能力得分)second_pursue_of_excellence models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue,verbose_name追求卓越得分)second_communication_ability models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue,verbose_name沟通能力得分)second_pressure_score models.DecimalField(decimal_places1, nullTrue, max_digits2, blankTrue,verbose_name抗压能力得分)second_advantage models.TextField(max_length1024, blankTrue, verbose_name优势)second_disadvantage models.TextField(max_length1024, blankTrue, verbose_name顾虑和不足)second_result models.CharField(max_length256, choicesINTERVIEW_RESULT_TYPE, blankTrue,verbose_name专业复试结果)second_recommend_position models.CharField(max_length256, blankTrue, verbose_name建议方向或推荐部门)second_interviewer models.CharField(max_length256, blankTrue, verbose_name专业复试面试官)second_remark models.CharField(max_length135, blankTrue, verbose_name专业复试备注)# HR终面hr_score models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR复试综合等级)hr_responsibility models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR责任心)hr_communication_ability models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR坦诚沟通)hr_logic_ability models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR逻辑思维)hr_potential models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR发展潜力)hr_stability models.CharField(max_length10, choicesHR_SCORE_TYPE, blankTrue,verbose_nameHR稳定性)hr_advantage models.TextField(max_length1024, blankTrue, verbose_name优势)hr_disadvantage models.TextField(max_length1024, blankTrue, verbose_name顾虑和不足)hr_result models.CharField(max_length256, choicesINTERVIEW_RESULT_TYPE, blankTrue,verbose_nameHR面试结果)hr_interviewer models.CharField(max_length256, blankTrue, verbose_nameHR面试官)hr_remark models.CharField(max_length135, blankTrue, verbose_nameHR复试备注)creator models.CharField(max_length256, blankTrue, verbose_name候选人数据的创建人)created_date models.DateTimeField(auto_now_addTrue, verbose_name创建时间)modified_date models.DateTimeField(auto_now_addTrue, nullTrue, blankTrue, verbose_name更新时间)last_editor models.CharField(max_length256, blankTrue, verbose_name最后编辑者)class Meta:db_table candidateverbose_name 应聘者verbose_name_plural 应聘者def __str__(self):return self.username 然后在 admin.py 文件注册数据模型并且展示时隐藏一些字段 from django.contrib import admin
from interview.models import Candidateclass CandidateAdmin(admin.ModelAdmin):exclude (creator,created_date,modified_date)list_display (username,city,bachelor_school,first_score,first_result,first_interviewer,second_result,second_interviewer,hr_score,hr_result,last_editor)admin.site.register(Candidate,CandidateAdmin) 再到 setting.py 文件注册应用 INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles,jobs,interview
] 最后执行数据库迁移还是那两个命令 makemigrations
migrate 效果图如下 页面分组展示 大家看到这个页面其实非常长因为我们的字段实在是太多了用起来很复杂所以面试官也好还是hr也好他们其实不太清楚哪些内容是他需要填的所以我们对这个页面进行优化把这个页面的内容分组展示 为了方便我们使用 pycharm 的代码编辑器新建一个文本文档把 models.py 里面的字段粘贴过来然后在这个文件里面去做批量编辑。 首先 ctrl r 来做一个正则表达式的替换输入 .*$ 然后点击星号匹配再点击 replace all 替换掉所有再删除一些多余的字段 然后再输入一个空格再点击 replace all 替换掉所有的空格 然后再输入 ^ 和 再点击 replace all 替换开头为 然后再输入 $ 和 再点击 replace all 替换结尾为 然后再输入 $ 和 再点击 replace all 替换结尾为 最后点 edit 这里有个 join line可以把字段都连起来 再删除一些多余的标点最后的成果如下 #基础信息,学校与学历信息,综合能力测评成绩,笔试测评成绩,
userid, username, city, phone, email, apply_position, born_address, gender, candidate_remark, bachelor_school, master_school, doctor_school, major, degree, test_score_of_general_ability, paper_score,#第一轮面试记录,
first_score, first_learning_ability, first_professional_competency, first_advantage, first_disadvantage, first_result, first_recommend_position, first_interviewer, first_remark,#第二轮面试记录,
second_score, second_learning_ability, second_professional_competency, second_pursue_of_excellence, second_communication_ability, second_pressure_score, second_advantage, second_disadvantage, second_result, second_recommend_position, second_interviewer, second_remark,#HR终面,
hr_score, hr_responsibility, hr_communication_ability, hr_logic_ability, hr_potential, hr_stability, hr_advantage, hr_disadvantage, hr_result, hr_interviewer, hr_remark, 然后把这些字段添加到 admin.py 文件的函数里同时在字段之前添加小括号来分小组让一行可以展示多个数据 class CandidateAdmin(admin.ModelAdmin):...fieldsets ((None,{fields:(userid, (username, city), (phone, email), (apply_position, born_address), (gender, candidate_remark), (bachelor_school, master_school, doctor_school), (major, degree), (test_score_of_general_ability, paper_score))}),(第一轮面试记录, {fields: ((first_score, first_learning_ability, first_professional_competency), first_advantage, first_disadvantage, first_result, first_recommend_position, first_interviewer, first_remark)}),(第二轮专业复试记录, {fields: ((second_score, second_learning_ability, second_professional_competency), (second_pursue_of_excellence, second_communication_ability, second_pressure_score), second_advantage, second_disadvantage, second_result, second_recommend_position, second_interviewer, second_remark)}),(HR复试记录, {fields: ((hr_score, hr_responsibility, hr_communication_ability), (hr_logic_ability, hr_potential, hr_stability), hr_advantage, hr_disadvantage, hr_result, hr_interviewer, hr_remark)})) 刷新界面发现已经分好组了。这里我就不截图了太长。 导入候选人 csv 文件 接下来我们再做进一步优化一般我们都不会自己去输入候选人的基本信息而是会拿到候选人的 excel 表或者 csv 文件那么如何导入候选人 csv 文件呢 我们在 interview 应用下创建文件夹目录 management/commands 创建 import_candidates.py 文件添加如下代码 import csvfrom django.core.management import BaseCommand
from interview.models import Candidateclass Command(BaseCommand):help 从csv导入候选人基本信息def add_arguments(self, parser):parser.add_argument(--path, typestr)def handle(self, *args, **options):path options[path]#编码格式选择合适的with open(path, rt,encodinggbk) as f:#csv分割符选择合适的不选默认为,分割#reader csv.reader(f,dialectexcel,delimiter;)reader csv.reader(f, dialectexcel)for row in reader:candidate Candidate.objects.create(usernamerow[0],cityrow[1],phonerow[2],bachelor_schoolrow[3],majorrow[4],degreerow[5],test_score_of_general_abilityrow[6],paper_scorerow[7]) 展示一下 excel 的内容 然后把 excel 文件导出为 csv 格式文件并删除第一行如下图 在 pycharm 的 run manage.py task 输入命令 import_candidates --path C:/Users/ASUS/Desktop/candidates.csv 刷新界面发现导入成功 提高查询效率 这个时候系统里面有很多简历了成百上千的简历里面要查找特定候选人的简历或者按照状态来查询待面试或者已经面试通过的候选人查找的效率比较低希望能够快速查询跟筛选接下来我们实现下面的两个功能。 第一个能够按照名字、手机号码学校来查询候选人 第二个能够按照初试的结果HR 复试的结果面试官来筛选然后也能够按照复试结果来排序复试通过的优先排在前面 修改 admin.py 文件为下面的代码 from django.contrib import admin
from interview.models import Candidate
from datetime import datetimeclass CandidateAdmin(admin.ModelAdmin):exclude (creator,created_date,modified_date)list_display (username,city,bachelor_school,first_score,first_result,first_interviewer,second_result,second_interviewer,hr_score,hr_result,last_editor)# 筛选条件list_filter (city,first_result,second_result,hr_result,first_interviewer,second_interviewer,hr_interviewer)# 查询字段search_fields (username,phone,email,bachelor_school)# 自动排序字段ordering (hr_result,second_result,first_result)# 分组展示字段fieldsets ((None,{fields:(userid, (username, city), (phone, email), (apply_position, born_address), (gender, candidate_remark), (bachelor_school, master_school, doctor_school), (major, degree), (test_score_of_general_ability, paper_score))}),(第一轮面试记录, {fields: ((first_score, first_learning_ability, first_professional_competency), first_advantage, first_disadvantage, first_result, first_recommend_position, first_interviewer, first_remark)}),(第二轮专业复试记录, {fields: ((second_score, second_learning_ability, second_professional_competency), (second_pursue_of_excellence, second_communication_ability, second_pressure_score), second_advantage, second_disadvantage, second_result, second_recommend_position, second_interviewer, second_remark)}),(HR复试记录, {fields: ((hr_score, hr_responsibility, hr_communication_ability), (hr_logic_ability, hr_potential, hr_stability), hr_advantage, hr_disadvantage, hr_result, hr_interviewer, hr_remark)}))def save_model(self, request, obj, form, change):obj.last_editor request.user.usernameif not obj.creator:obj.creator request.user.usernameobj.modified_date datetime.now()obj.save()admin.site.register(Candidate,CandidateAdmin) 效果图 导出候选人面试结果 csv 文件 现在我们再加一个功能将数据导出为 csv 文件修改 admin.py 文件如下 from django.contrib import admin
from interview.models import Candidate
from datetime import datetime
from django.http import HttpResponse
import csvexportable_fields (username,city,phone,bachelor_school,degree,first_result,first_interviewer,second_result,second_interviewer,hr_score,hr_result)def export_model_as_csv(modeladmin,request,queryset):response HttpResponse(content_typetext/csv)field_list exportable_fields#可以使用 request 中的 User-Agent 进行客户端系统判断如果用户的系统是 Windows那么给导出的文件编码设置为带有 BOM 的 UTF-8否则使用 UTF-8response.charset utf-8-sig if Windows in request.headers.get(User-Agent) else utf-8#Content-Disposition 响应标头指示回复的内容该以何种形式展示是以内联的形式即网页或者页面的一部分还是以附件的形式下载并保存到本地response[Context-Disposition] attachment;filenamerecruitment-candidates-list-%s.csv %(datetime.now().strftime(%Y-%m-%d-%H-%M-%S))# 写入表头print(response[Context-Disposition])writer csv.writer(response)writer.writerow([queryset.model._meta.get_field(f).verbose_name.title() for f in field_list])for obj in queryset:# 单行的记录(各个字段的值)写入csv文件csv_line_values []for field in field_list:field_object queryset.model._meta.get_field(field)field_value field_object.value_from_object(obj)csv_line_values.append(field_value)writer.writerow(csv_line_values)return response#国际化文本
export_model_as_csv.short_description 导出为CSV文件class CandidateAdmin(admin.ModelAdmin):actions [export_model_as_csv]exclude (creator,created_date,modified_date)list_display (username,city,bachelor_school,first_score,first_result,first_interviewer,second_result,second_interviewer,hr_score,hr_result,last_editor)# 筛选条件list_filter (city,first_result,second_result,hr_result,first_interviewer,second_interviewer,hr_interviewer)# 查询字段search_fields (username,phone,email,bachelor_school)# 自动排序字段ordering (hr_result,second_result,first_result)# 分组展示字段fieldsets ((None,{fields:(userid, (username, city), (phone, email), (apply_position, born_address), (gender, candidate_remark), (bachelor_school, master_school, doctor_school), (major, degree), (test_score_of_general_ability, paper_score))}),(第一轮面试记录, {fields: ((first_score, first_learning_ability, first_professional_competency), first_advantage, first_disadvantage, first_result, first_recommend_position, first_interviewer, first_remark)}),(第二轮专业复试记录, {fields: ((second_score, second_learning_ability, second_professional_competency), (second_pursue_of_excellence, second_communication_ability, second_pressure_score), second_advantage, second_disadvantage, second_result, second_recommend_position, second_interviewer, second_remark)}),(HR复试记录, {fields: ((hr_score, hr_responsibility, hr_communication_ability), (hr_logic_ability, hr_potential, hr_stability), hr_advantage, hr_disadvantage, hr_result, hr_interviewer, hr_remark)}))def save_model(self, request, obj, form, change):obj.last_editor request.user.usernameif not obj.creator:obj.creator request.user.usernameobj.modified_date datetime.now()obj.save()admin.site.register(Candidate,CandidateAdmin) 效果图 点击执行成功下载打开文件效果如下 目前这个导出 csv 文件的文件名会显示乱码并不能输出我们期望的文件名暂时我并没有找到解决方法如果有写出来的大佬务必私信我感谢 第四阶段完成