定制app开发【Django | 开发】面试招聘网站(增加csv,excel导出&企业域账号集成&日志管理功能)

🤵‍♂️ 个人主页:
👨‍💻 作者简介:CSDN定制app开发内容合伙人,定制app开发全栈领域优质创作者。

🌐 定制app开发推荐一款找工作神器网站:
定制app开发还没账户的小伙伴 定制app开发开始刷爆题库,定制app开发速速通关面试吧🙋‍♂️

定制app开发该文章收录专栏
✨✨

文章目录

一、实现excel定制app开发表格导入数据(工具)

  • HR定制app开发需要人肉输入应聘者数据,定制app开发非常枯燥和耗时,定制app开发所以我们进行产品的第二次迭代 – 实现候选人数据的导入

在应用interview创建managment文件以及该目录下command文件,创建import_candidate.py进行脚本操作、

需要存入的数据

  • import_candidates.py (这里选择使用pandas读取数据)
import pandas as pdfrom django.core.management import BaseCommandfrom interview.models import Candidate# python manage.py import_candidates --path file.csvclass Command(BaseCommand):    help = '从一个csv导入数据,并存贮到数据库'    # 添加一个长命令 Linux中 -- 表示长命令    def add_arguments(self, parser):        parser.add_argument('--path', type=str)  # 所接受参数为一个字符串    # 处理逻辑    def handle(self, *args, **options):        path = options['path']  # 从命令行参数读取 path 存贮的路径        # with open(path, 'r', encoding='gbk') as f:        #     reader = csv.reader(f, dialect='excel')        #     for row in reader:        #         print(row[0])        candidate_data = pd.read_csv(path, encoding='gbk', )        for row in range(len(candidate_data)):            data = list(candidate_data.iloc[row, :])            # 创建对象不能Candidate()这是一个类实例,需要通过objects 对象来与数据库交互            candidate = Candidate.objects.create(                user_name=data[0],                city=data[1],                phone=data[2],                bachelor_school=data[3],                major=data[4],                degree=data[5],                test_score_of_general_ability=data[6],                page_score=data[7]            )            candidate.save()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 命令行输入
python manage.py import_candidates --path ~/应聘者数据.csv
  • 1


此时HR非常开心,不用一个一个录入候选人,我们的第二轮开发实现,接下来我们实现 列表查询和筛选

二、列表查询和筛选&页面再优化

希望能通过快速筛选得到数据,要求如下


强烈建议看官方文档,比任何教程都要强

  • admin.py 文件
from django.contrib import adminfrom interview.models import Candidate# Register your models here.@admin.register(Candidate)class CandidateAdmin(admin.ModelAdmin):    list_display = ('user_id', 'user_name', 'first_result', 'second_result', 'hr_result', 'create_time', 'modify_time')    # 定义集合的字段列表    fieldsets = (        # 第一个元素表示分组展现的名字,第二元素是一个map        (None, {'fields': ("user_id", ("user_name", "email", "gender", "phone",),                           ("apply_position", "degree"),                           ("city", "born_address"),                           ("doctor_school", "bachelor_school", "master_school", "major",), ("page_score",                                                                                             "test_score_of_general_ability",                                                                                             "candidate_remark",),                           ), }),        ('第一轮面试', {'fields': ("first_score", "first_result", "second_interviewer",                              ), 'classes': ('collapse',), "description": '请由面试官输入该信息'}),        ('第二轮面试', {'fields': ("second_score", "second_result", "first_interviewer",                              ), 'classes': ('collapse',), "description": '请由面试官输入该信息'}),        ('第三轮面试', {'fields': ("hr_score", "hr_result", "hr_interviewer",                              ), 'classes': ('collapse',), "description": '请由面试官输入该信息'})    )    list_editable = ('user_id',)  # 可直接在页面修改的数据    list_display_links = ('user_name',)  # 默认为第一个columns 不想要设置为None 超链接跳转到form表单    list_per_page = 10  # 每个页面显示多少条数据    # list_max_show_all = 5 每个页面点击show_all最多显示数据    list_filter = ('first_result', 'second_result', 'hr_result')  # 按照成绩筛选名字    # list_select_related = ('user_name', 'first_result')    # readonly_fields = ( 'modify_time',) # in_list_page non-editable and readonly    # save_as = True  # 将 save_and_add_another  replace to save_as    search_fields = ('user_name', 'first_result', 'second_result', 'hr_result',)  # 设置可搜索内容    ordering = ('hr_result', 'second_result','first_result' ,)  # 默认按照成绩排序好
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 效果:

三、企业域账号集成

目的:省去多余的账号管理(每个人都要注册一个账号,过于麻烦)

  • LDAP 成员页面
  • 在服务器的服务

1) 安装应用

pip install django-python3-ldap 
  • 1

  • setting.py应用将app加进来
  • OpenLDAP设置

这样用户可以有两个账号,一个是使用LDAP账号,一个是admin账号,每个员工登陆一下时会需要在每次登录自动录入账号到user群,但却由于显示非员工无法登录,需要在admin后台修改其为员工然后登录,但是这样需要一个一个登录,效率低下

  • 解决:通过manage脚本导入用户信息

python manage.py ldap_sync_users

2) 设置面试官和HR权限(群组)

  • HR的管理页面

四、添加导出为csv功能

  • 添加action,指向不同函数进行处理

操作函数

import csvfrom datetime import datetime# 注册为 action@admin.action(description='导出为csv文件')def export_model_as_csv(modeladmin, request, queryset):    # 告诉浏览器以附件处理    response = HttpResponse(content_type="text/csv")    field_list = ['user_name', 'first_result', "first_interviewer", 'second_result', "second_interviewer",                  'hr_result', "hr_interviewer", 'modify_time']    # attachment 类型是附件 名字为 ""(为字符串,需要单双引号)    response['Content-Disposition'] = 'attachment; filename= "recruitment_candidate_list_%s.csv"' % (        datetime.now().strftime('%Y-%m-%d,%H-%M-%S')    )    # candidate_list = pd.DataFrame(columns=columns)    # _meta 是一个Options对象 有get_filed and get_fields 两个方法,得到对象关键字的大写    writer = csv.writer(response)    writer.writerow([queryset.model._meta.get_field(f).verbose_name.title() for f in field_list])    # columns_name = [queryset.model._meta.get_field(f).verbose_name.title() for f in columns]    for obj in queryset:        ## 单行记录        csv_line_values = []        for field in field_list:            field_object = queryset.model._meta.get_field(field)            field_values = field_object.value_from_object(obj)            csv_line_values.append(field_values)        writer.writerow(csv_line_values)    return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

adminmodel类中引入action

@admin.register(Candidate)class CandidateAdmin(admin.ModelAdmin):    list_display = (        'user_id', 'user_name', 'first_result', "first_interviewer", 'second_result', "second_interviewer", 'hr_result',        "hr_interviewer", 'modify_time')    # import actions to use    actions = [export_model_as_csv, ]  ···  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 效果

六、添加excel导出功能(样式)

此时HR需要能够导出一个具有好看样式的表格,可以统计S分数的候选人,此时我们使用python中处理excel表格文件的三板斧 xlrd - xlwt - xlutils

  • 在需要导入excel文件,我们可以用xlrd-xlutils-xlwt,通过xlutilsbook转换为workbook ,进行读写操作

这里现在只需要用到xlrt

def setStyle(name, height=200, font_color=256, background_color=0x40, background=False, bold=False, align=True,             border=False, border_size=1):	"""	xlwt样式写入设置	"""	style = xlwt.XFStyle()  # 初始化样式	if background:		# 创建背景模式对像		pattern = xlwt.Pattern()		# 固定样式		pattern.pattern = xlwt.Pattern.SOLID_PATTERN  # May be: NO_PATTERN, SOLID_PATTERN, or 0x00 through 0x12		pattern.pattern_fore_colour = background_color  # 设置模式颜色 May be: 8 through 63. 0 = Black, 1 = White, 2 = Red, 3 = Green, 4 = Blue, 5 = Yellow, 6 = Magenta, 7 = Cyan, 16 =		# Maroon, 17 = Dark Green, 18 = Dark Blue, 19 = Dark Yellow , almost brown), 20 = Dark Magenta, 21 = Teal, 22 = Light Gray, 23 = Dark Gray, the list goes on...		style.pattern = pattern	font = xlwt.Font()  # 为样式创建字体	# 字体类型:比如宋体、仿宋也可以是汉仪瘦金书繁	font.name = name	# 设置字体颜色	font.colour_index = font_color	# 字体大小	font.height = height	# 字体加粗	font.bold = bold	# 定义格式	style.font = font	if border:		# 框线		borders = xlwt.Borders()		borders.left = border_size		borders.right = border_size		borders.top = border_size		borders.bottom = border_size		style.borders = borders	# 细实线:1,小粗实线:2,细虚线:3,中细虚线:4,大粗实线:5,双线:6,细点虚线:7	# 大粗虚线:8,细点划线:9,粗点划线:10,细双点划线:11,粗双点划线:12,斜点划线:13	if align:		# 设置单元格对齐方式		al = xlwt.Alignment()		# 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)		al.horz = 0x02		# 0x00(上端对齐)、 0x01(垂直方向上居中对齐)、0x02(底端对齐)		al.vert = 0x01		style.alignment = al	return style# 注册为 action@admin.action(description='导出为excel文件')def export_model_as_excel(modeladmin, request, queryset):	# 告诉浏览器以附件处理	response = HttpResponse(content_type='application/vnd.ms-excel')	field_list = ['user_name', 'first_result', "first_interviewer", 'second_result', "second_interviewer",	              'hr_result', "hr_interviewer", "modify_time"]	# attachment 类型是附件 名字为 ""(为字符串,需要单双引号)	response['Content-Disposition'] = 'attachment; filename= "recruitment_candidate_list_%s.xlsx"' % (		datetime.now().strftime('%Y-%m-%d,%H-%M-%S')	)	# 使用 xlwt 生成表格	title = ['应聘候选人信息']	wb = xlwt.Workbook(encoding='utf-8')  # 创建一个excel  #ascii'可视为'utf-8'的一部分,so用'utf-8'更好	ws = wb.add_sheet('候选人')  # 新建一个工作表	ws.write_merge(0, 1, 0, len(field_list) - 1, title, style=setStyle('微软雅黑', height=200, font_color=256,  bold=True, border=True, border_size=1))	for col, name in enumerate(field_list):  # 变为枚举类型,默认从0开始,		ws.write(2, col, queryset.model._meta.get_field(name).verbose_name.title(), style=setStyle('微软雅黑', height=200, font_color=0x40, background=True, background_color=0x4682B4))	row = 3  # 从第三行开始	# style_date = xlwt.XFStyle()	# style_date.num_format_str = 'M/D/YY h:mm'	S_sum = 0	for obj in queryset:		columns = 0		# # 单行记录		for field in field_list:			field_object = queryset.model._meta.get_field(field)			field_values = field_object.value_from_object(obj)			logger.warning(type(field_values))			if type(field_values) == type(datetime.today()):  # 判断是否为datetime数据类型,并指定数据为时间格式				field_values = field_values.strftime('%Y/%m/%d,%H:%M:%S')				ws.write(row, columns, field_values)			else:				# 累加S级别人数				if field_values == 'S':					S_sum += 1				ws.write(row, columns, field_values)			columns += 1		# 时间行宽增大		row += 1	ws.col(columns - 1).width = 5000	ws.col(columns - 2).width = 5000	ws.write(row + 2, len(field_list) - 2, '终面S级别人数:', setStyle(name='仿宋', bold=True))	ws.write(row + 2, len(field_list) - 1, S_sum)	logger.warning('{} exported {} candidate records'.format(request.user, len(queryset)))	wb.save(response)  # 保存到文件类对象	return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 导出样式

五、记录日志以方便排查问题

1) 项目配置

  • 记录详细的日志信息可以快速排查问题

python格式一样,使用 dictConfig格式来定义日志信息,在处理级别时是按照过滤原则handler处理其级别信息上传到记录器 记录器再根据自身级别过滤上传root再过滤

  • 优化配置(,强烈建议看文档)

在项目的setting.py文件中进行如下配置

# log recordLOGGING = {	'version': 1,  # 必须	"disable_existing_loggers": False,  # 设置其他日志同时记录	'handlers': {		'console': {  # handler 名称(表示控制台输出)			"class": "logging.StreamHandler",  # 在控制台流 类			'formatter': 'simple',			'level': 'INFO'		},		'file': {  # handler 名称 (表示文件输出)			'level': 'INFO',			'class': 'logging.FileHandler',  # 文件流类			'formatter': 'simple',			# 得到完整路径并拼接			'filename': os.path.join(BASE_DIR, 'logs/debug.log'),		},	},	'formatters': {		# simple 类		'simple': {			'format': '%(asctime)s , %(name)s [ %(levelname)s ] %(message)s',		}	},	# 根日志记录器(父记录器)	'root': {		'handlers': ['console', 'file'],  # 记录到文件和控制台中		'level': 'INFO',	},	'loggers': {		'django': {			'handlers': ['file'],			'level': 'DEBUG',			'propagate': True,		}	}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 运行服务器查看
python manage.py runserver 0.0.0.0:8000
  • 1

2)在admin中配置python的logging模块

# 得到 当前日志记录对象# logging.basicConfig(level=logging.DEBUG,format="'%(asctime) %(name) %(levelname) %(message)")logger = logging.getLogger(__name__)	def ·······			·······    # 输出 导出对象以及条数(只有warning以上才会被打印,可以自己配置)    logger.warning('{} exported {} candidate records'.format(request.user, len(queryset)))    return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10


参考文献:

			        🤞到这里,如果还有什么疑问🤞		🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩			🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳
  • 1
  • 2
  • 3
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发