Django企业招聘后台管理系统开发实战七

第七阶段

为后台管理系统换风格

安装皮肤包

pip install django-grappelli

在 setting.py 注册

INSTALLED_APPS = [
    'grappelli',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'jobs',
    'interview'
]

在 recruitment 的 urls.py 添加 path

urlpatterns = [
    path('',include("jobs.urls")),
    path('grappelli/',include('grappelli.urls')),
    path('admin/', admin.site.urls)
]

效果图:

 细节完善

修改站点标题

在 recruitment 的 urls.py 添加如下代码

from django.utils.translation import gettext as _

admin.site.site_header = _('招聘管理系统')

效果图

设置提示字段

在 interview 的 models.py 文件为候选人添加字段参数 help_text

class Candidate(models.Model):
    ...

    first_score = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True, verbose_name='初始分', help_text='1-5分,级优秀: >= 4.5,优秀: 4-4.4,良好: 3.5-3.9,一般: 3-3.4,较差: <3分')
    ...
    second_score = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True, verbose_name='专业复试得分',help_text='1-5分,级优秀: >= 4.5,优秀: 4-4.4,良好: 3.5-3.9,一般: 3-3.4,较差: <3分')
    ...
    hr_score = models.CharField(max_length=10, choices=HR_SCORE_TYPE, blank=True,verbose_name='HR复试综合等级',help_text='1-5分,级优秀S: >= 4.5,优秀A: 4-4.4,良好B: 3-3.9,一般C: <3分')
    

效果图

面试官与用户关联

在 interview 的 models.py 文件为候选人修改面试官字段

把下面的字段

class Candidate(models.Model):
    ...
    first_interviewer = models.CharField(max_length=256, blank=True, verbose_name='初试面试官')
    ...
    second_interviewer = models.CharField(max_length=256, blank=True, verbose_name='专业复试面试官')
    ...
    hr_interviewer = models.CharField(max_length=256, blank=True, verbose_name='HR面试官')

改为外键,并设置限制的群组选择

from django.contrib.auth.models import User

class Candidate(models.Model):
    ...
    first_interviewer_user = models.ForeignKey(User,related_name='first_interviewer_user', blank=True, null=True,on_delete=models.CASCADE,limit_choices_to={'groups__name': 'interviewer'},verbose_name='初试面试官')
    ...
    second_interviewer_user = models.ForeignKey(User,related_name='second_interviewer_user', blank=True, null=True,on_delete=models.CASCADE,limit_choices_to={'groups__name': 'interviewer'},verbose_name='复试面试官')
    ...
    hr_interviewer_user = models.ForeignKey(User,related_name='hr_interviewer_user', blank=True, null=True,on_delete=models.CASCADE,limit_choices_to={'groups__name': 'hr'},verbose_name='HR面试官')

同时在 interview 的 admin.py 文件把 CandidateAdmin 类中的

first_interviewer ,second_interviewer,hr_interviewer 字段名称修改为

first_interviewer_user,second_interviewer_user,hr_interviewer_user

然后做数据库迁移,不多说还是那两个命令,执行完效果图(我这里注册了 cx,gsy 作为面试官,hp 作为 hr)

设置面试官只读

在 interview 的 admin.py 文件添加只读字段

class CandidateAdmin(admin.ModelAdmin):
    ...
    # 设置面试官组只读字段
    ###readonly_fields = ('first_interviewer_user','second_interviewer_user')
    def get_group_names(self,user):
        group_names = []
        for g in user.groups.all():
            group_names.append(g.name)
        return group_names

    def get_readonly_fields(self, request, obj):
        group_names = self.get_group_names(request.user)
        if 'interviewer' in group_names:
            logger.info("interviewer is in user's group for %s" % request.user.username)
            return ('first_interviewer_user', 'second_interviewer_user')
        return ()

admin 的效果图

interviewer 的效果图

列表页编辑字段

这样就不用每次进详情页编辑面试官,编辑完记得保存哦

只有管理员和hr可以直接编辑字段,但是 django 没有内置 get_list_editable 函数,需要覆盖掉父类的 list_editable 字段

class CandidateAdmin(admin.ModelAdmin):
    ...
    # 设置只有管理员和hr可以直接编辑字段
    default_list_editable = ('first_interviewer_user','second_interviewer_user')

    def get_list_editable(self, request, obj):
        group_names = self.get_group_names(request.user)
        if request.user.is_super_user or 'hr' in group_names:
            return self.default_list_editable
        return ()

    def get_changelist_instance(self, request):
        self.list_editable = self.get_list_editable(request)
        return super(CandidateAdmin,self).get_changelist_instance(request)

hr 效果图

interviewer 效果图

定制面试管权限

数据权限

修改 fieldsets 字段

class CandidateAdmin(admin.ModelAdmin):
    ...
    # 分组展示字段
    default_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_user", "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_user", "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_user", "hr_remark")})
    )

    default_fieldsets_first = (
        (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_user", "first_remark")}),
    )

    default_fieldsets_second = (
        (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_user", "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_user", "second_remark")})
    )

    # 一面面试官仅填写一面反馈,二面面试官可以填写二面反馈
    def get_fieldsets(self, request, obj=None):
        group_names = self.get_group_names(request.user)
        if 'interviewer' in group_names and obj.first_interviewer_user == request.user:
            return self.default_fieldsets_first
        if 'interviewer' in group_names and obj.second_interviewer_user == request.user:
            return self.default_fieldsets_second
        return self.default_fieldsets

这里我就不放效果图了,大家自行演示,因为上述代码过长,所以可以单独放在一个 python 文件中,这里就不演示了

数据集权限

对于非管理员,非HR,获取自己是一面面试官或者二面面试官的候选人集合

添加函数

from django.db.models import Q

class CandidateAdmin(admin.ModelAdmin):
    ...
    # 对于非管理员,非HR,获取自己是一面面试官或者二面面试官的候选人集合:
    def get_queryset(self, request):  # show data only owned by the user
        qs = super(CandidateAdmin, self).get_queryset(request)
        group_names = self.get_group_names(request.user)
        if request.user.is_superuser or 'hr' in group_names:
            return qs
        return Candidate.objects.filter(
            Q(first_interviewer_user = request.user) | Q(second_interviewer_user = request.user))

效果图不展示了

功能权限

在 interview 的 models.py 文件添加代码

class Candidate(models.Model):
    ...
    class Meta:
        ...
        # 导出csv权限,通知面试官面试权限
        permissions = [
            ("export","can export candidate list"),
            ("notify", "notify interviewer for candidate reviews")
        ]

返回 admin.py 文件,添加代码

export_model_as_csv.allowed_permissons = ('export')

class CandidateAdmin(admin.ModelAdmin):
    actions = [export_model_as_csv]
    ### 当前用户是否有权限
    def has_export_permissons(self,request):
        opts = self.opts
        return request.user.has_perm('%s.%s' % (opts.app_label, "export"))

这时候需要做一次数据库迁移,还是那两个命令

然后为 hr 组添加 export 和 notify 权限

测试效果自行验证

第七阶段完成!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海绵不是宝宝817

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值