• 【Django | 开发】面试招聘信息网站(划分面试官权限&集成钉钉消息)


    在这里插入图片描述

    该文章收录专栏
    —Django从(图文并茂轻松上手教程)专栏—✨!!

    🎏内容:
    【Djang | 增删改查】学生系统案例
    【Django | 项目搭建】快速搭建自己的项目
    【Django | allauth】登录_注册_邮箱验证_密码邮箱重置
    【Django | allauth】useprofile 用户模型扩展
    【Django | allauth】重写allauth重置密码方法
    【Django | 开发】面试招聘信息网站(快速搭建核心需求)
    【Django | 开发】面试招聘信息网站(增加csv,excel导出&日志管理功能)
    【Django | 开发】面试招聘信息网站(处理产品细节和权限&美化页面样式)

    一、设置面试官权限

    在这里插入图片描述

    1)数据权限

    • 通过get_list_fieldsets控制admin选项option中的fieldsets 实现

    预期效果

    1. hr 和超级用户 可以看到全部信息
    2. 一面面试官只能看到自己负责的一面面试信息
    3. 二面面试官只能看到自己负责二面面试信息
    4. 普通管理员(还未被指定一面或者二面面试官)只能修改候选人信息

    代码实现(核心代码)

    	# 定义集合的字段列表
    	default_fieldsets = (
    		# 第一个元素表示分组展现的名字,第二元素是一个map
    		·······
    	)
    	default_fieldsets_hr = (·······)
    	# 定义集合的字段列表
    	default_fieldsets_second = (·······)
    	# 定义集合的字段列表
    	default_fieldsets_first = (·······)
    
    	def get_fieldsets(self, request, obj=None):
    		group_name = self.get_group_name(request.user)
    		# obj 是对应修改对象,和action方法queryset一样
    		if 'interviewer' in group_name and request.user == obj.first_interviewer_user: # 判断是否对应一面面试官
    			logger.info("The interviewer is the first interviewer for user %s"% obj.user_name)
    			return default_fieldsets_first
    		elif 'interviewer' in group_name and request.user == obj.second_interviewer_user:
    			logger.info("The interviewer is the second interviewer for user %s" % obj.user_name)
    			return default_fieldsets_second
    		elif request.user.is_superuser or 'HR' in group_name:
    			logger.info("The interviewer is the HR  for user %s or superuser" % obj.user_name)
    			return default_fieldsets_hr
    		return default_fieldsets
    
    	def get_group_name(self, user):
    		group_name = []
    		for g in user.groups.all():  # 循环groups对象列表
    			group_name.append(g.name)  # 附加对象的名字
    		return group_name
    
    • 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
    • 由于fieldset代码过长,我们将设置的fieldset放到脚本candidate_fieldset脚本文件中,直接引入进来。
      在这里插入图片描述

    HR 和超级用户
    在这里插入图片描述
    一面面试官

    在这里插入图片描述
    二面面试官

    在这里插入图片描述

    2) 数据集的权限控制

    • 通过重写 get_queryset进行条件判断,并借助Q对象对数据库SQL语句进行or and组合实现需求
    from django.db.models import Q
    
    	# 列表页显示默认先运行get_queryset,没有重写则全部显示
    	# 此时显示的数据集是对于Candidate模型的,不影响其他模型
    	def get_queryset(self, request):
    		qs = super(CandidateAdmin, self).get_queryset(request)
    
    		group_name = self.get_group_name(request.user)
    		# hr or superuser
    		if 'HR' in group_name or request.user.is_superuser:
    			return qs
    		# interviewer
    		return Candidate.objects.filter(  # Q对象 可进行and or 配合位或运算符
    			Q(first_interviewer_user=request.user) | Q(second_interviewer_user=request.user))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    成功实现
    在这里插入图片描述

    在这里插入图片描述

    3) action行为权限

    在添加群组时我们为interviewer群组添加了增删改查应聘者的权限,这里再为普通面试官添加不可导出为csv action行为 的权限以及不可删除对象delete_selected)的权限

    1. 方法一:添加权限实现(为Candidate模型Meta 为其设置自定义权限(元组))
    2. 方法二:有条件的启用或禁用行为(get_actions
    3. 方法三:全局禁用,局部使用
      https://docs.djangoproject.com/zh-hans/4.0/ref/contrib/admin/actions/ (各种方法文档都有例子)
    • 方法一:添加权限实现(为Candidate模型Meta 为其设置自定义权限(元组))
    
    ·······
    	class Meta:
    		db_table = 'candidate'
    		verbose_name = '应聘者'
    		verbose_name_plural = '应聘者'  # 复数形式
    
    		permissions = (
    			('export_as_csv_or_excel', "Can export candidate list"),
    			('notify_interviewer', "Can notify interviewer")
    		)
    ······
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • action装饰器ModelAdmin类加上权限设置( permissions 的值必须是一个 列表或元组!传一个字符串会拆成各个字符
    
    # 注册为 action       permissions 的值必须是一个 列表或元组!传一个字符串会拆成各个字符
    @admin.action(description='导出为csv文件', permissions=('export_as_csv_or_excel'))
    def export_model_as_csv(modeladmin, request, queryset):
    	·······
    
    # 注册为 action
    @admin.action(description='导出为excel文件', permissions=('export_as_csv_or_excel'))
    def export_model_as_excel(modeladmin, request, queryset):
    	······
    
    	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    官方文档modeladmin配置

    You can specify any other value as long as you implement a corresponding has_[value]_permission(self, request) method on the ModelAdmin.(注意:这里的value就是你设置的权限)

    • admin代码

    总体代码思想,先在model模型添加Meta信息,数据库同步则会添加在群组权限设置中,
    然后对action行为添加permission权限,接着还必须要在modeladmin添加函数has_value_permission判断登录user是否has_perm(拥有权限),返回值为boolean, 我们可以看看permission 模型代码
    在这里插入图片描述

    
    # 全局禁用删除对象,需要使用需要在modeladmin加上该action
    # admin.site.disable_action('delete_selected') 不建议使用,可以通过权限设置
    
    
    @admin.register(Candidate)
    class CandidateAdmin(admin.ModelAdmin):
    	# import actions to use
    	actions = [export_model_as_csv, export_model_as_excel, 'delete_selected']
    	def has_export_as_csv_or_excel_permission(self, request):
    		"""Does the user have the export permission?"""
    		opts = self.opts
    		# return a boolean           判断是否权限            模型所在应用  权限名
    		return request.user.has_perm("%s.%s" % (opts.app_label, "export_as_csv_or_excel"))  # 是否有对应权限
    
      ······
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 这里的opts参数其实就是对应modelMeta
      在这里插入图片描述

    • 效果
      在这里插入图片描述
      在这里插入图片描述

    • 现在还无法看到权限,因为model模型Meta信息还没有同步到数据库(如果数据库auth用户验证模块没有这个定义,这里是不显示的)
      在这里插入图片描述

    • 数据迁移两把斧运行

    在这里插入图片描述
    成功
    在这里插入图片描述

    二、 钉钉群消息集成

    在这里插入图片描述

    1)简单shell测试

    在这里插入图片描述

    • 在应用interview创建脚本dingtalk.py
    # coding=utf-8
    # 引入聊天机器人
    from dingtalkchatbot.chatbot import DingtalkChatbot
    
    from django.conf import settings
    
    
    def send(message, at_mobiles=[]):
    	# 引用settings 中配置钉钉群中配置消息通知的WEB hook
    	webhook = settings.DINGTALK_WEB_HOOK
    
    	# 初始化机器人小丁 方法一
    	xiaoding = DingtalkChatbot(webhook)
    	# 方法二
    	# xiaoding = DingtalkChatbot(webhook,secret=secret)
    
    	# Text消息 @所有人
    	xiaoding.send_text(msg=('面试通知:%s' % message), at_mobiles=at_mobiles)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 创建群聊,选择自定义
      在这里插入图片描述
      在这里插入图片描述

    在这里插入图片描述

    • 将Webhook 卸载setting中
      在这里插入图片描述

    • 使用shell 测试

    In [2]: import interview.dingtalk
    
    In [3]: interview.dingtalk.send("通知!请哈利波速速救急")
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    也可以@面试官

    In [6]: interview.dingtalk.send("通知!请哈利波速速救急",['1343187782'])
    
    • 1

    在这里插入图片描述

    2)在admin后台添加通知面试官action

    在实际中,我们希望直接通知最近需要面试候选人得面试官,所以我们为应聘者添加一个action,被选中得应聘者可以直接发送到对应一面或二面面试官。

    • admin.py
    # 导入发送消息
    from .dingtalk import send
    
    # 注册为 action
    @admin.action(description='钉钉通知面试官', permissions=('notify_interviewer',))
    def notify_interviewer(modeladmin, request, queryset):
    	# 面试官对象
    	candidates = ""
    	interviewer = []
    	at_mobiles = []
    	for candidate in queryset:
    		candidates = candidate.user_name + ',' + candidates
    		if candidate.first_interviewer_user is not None:
    			interviewer.append(candidate.first_interviewer_user)
    		if candidate.second_interviewer_user is not None:
    			interviewer.append(candidate.second_interviewer_user)
    	# 集合去重
    	interviewer = set(interviewer)
    	for mobile in interviewer:
    		at_mobiles.append(mobile.profile.tel)
    
    	logger.info("%s interviewer have been notice" % len(interviewer))
    	logger.info(at_mobiles)
    	logger.info(interviewer)
    
    	send("%s 准备面试,以下面试官请准备面试工作" % candidates, at_mobiles=at_mobiles)
    
    
    
    @admin.register(Candidate)
    class CandidateAdmin(admin.ModelAdmin):
    	·······
    	# import actions to use
    	actions = [export_model_as_csv, export_model_as_excel, notify_interviewer]
    
    	def has_notify_interviewer_permission(self, request):
    		"""Does the user have the export permission?"""
    		opts = self.opts
    		# return a boolean           判断是否权限            模型所在应用  权限名
    		return request.user.has_perm("%s.%s" % (opts.app_label, "notify_interviewer"))  # 是否有对应权限
    
    • 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
    • 效果
      在这里插入图片描述

        		        🤞到这里,如果还有什么疑问🤞
        	🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩
        		🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳
      
      • 1
      • 2
      • 3
  • 相关阅读:
    linux进程间通信之信号量
    c++ 多态的
    分布式系统开发技术中的CAP定理原理
    Java Tomcat内存马——filter内存马
    vue 城市选择器的使用 element-china-area-data
    算法| ss 逻辑问题
    如何成为开源组件库NutUI的contributor:解决issue并提交PR
    基于协同过滤进行金融产品个性化推荐 代码+数据
    【word论文排版-公式】如何实现两栏格式公式居中,编号右对齐
    阿里云serverless从入门到进阶测评(阿里云/AWS/腾讯云)
  • 原文地址:https://blog.csdn.net/weixin_66526635/article/details/125787609