【Django快速开发实战】(1~29)使用Django创建一个基础应用:职位管理系统

本文档详述了一个基于Django构建的招聘管理系统,包括职位管理、候选人信息模型、Django项目结构、数据库同步、管理后台定制、CSV导入导出、日志记录、权限管理、面试官权限控制、用户注册与登录、简历上传、面试流程自动化等。此外,还介绍了如何使用Bootstrap美化页面、实现数据权限控制,并集成钉钉群消息通知。

1.总体描述

1.1产品需求:

在这里插入图片描述

1.2职位管理系统-建模

###

1.3 Django项目代码结构

在这里插入图片描述

  • 新增recruitment项目
django-admin startproject recruitment
  • 新增APP
python manage.py startapp job
  • settings.py安装APP
INSTALLED_APPS = [
    'jobs',
]
  • 同步数据库
python manage.py makemigrations
python manage.py migrate

05 | 开始Django之旅 :10分钟如何创建一个可以管理职位的后台

Jobs/models.py的Job模型

created_date 和 modified_date 为自动添加的时间。

from django.db import models
from django.contrib.auth.models import User

# Create your models here.
JobTypes = [
    (0,"技术类"),
    (1,"产品类"),
    (2,"运营类"),
    (3,"设计类"),
    (4,"市场营销类")
]

Cities = [
    (0,"北京"),
    (1,"上海"),
    (2,"深圳"),
    (3,"杭州"),
    (4,"广州")
]


class Job(models.Model):
    # Translators: 职位实体的翻译
    job_type = models.SmallIntegerField(blank=False, choices=JobTypes, verbose_name=("职位类别"))
    job_name = models.CharField(max_length=250, blank=False, verbose_name=("职位名称"))
    job_city = models.SmallIntegerField(choices=Cities, blank=False, verbose_name=("工作地点"))
    job_responsibility = models.TextField(max_length=1024, verbose_name=("职位职责"))
    job_requirement = models.TextField(max_length=1024, blank=False, verbose_name=("职位要求"))
    creator = models.ForeignKey(User, verbose_name=("创建人"), null=True, on_delete=models.SET_NULL)
    created_date = models.DateTimeField(verbose_name=("创建日期"), auto_now_add=True)
    modified_date = models.DateTimeField(verbose_name=("修改日期"), auto_now=True)

    class Meta:
        verbose_name = ('职位')
        verbose_name_plural = ('职位列表')

    def __str__(self):
        return self.job_name

在这里插入图片描述

06 | 产品体验优化:快速迭代完善应用

admin.py修改

save_model()使creator可以默认选择当前user。

from django.contrib import admin
from jobs.models import Job



class JobAdmin(admin.ModelAdmin):
    exclude = ('creator','created_date','modified_date')
    list_display = ('job_name', 'job_type', 'job_city', 'creator', 'created_date', 'modified_date')

    def save_model(self, request, obj, form, change):
        if obj.creator is None:
            obj.creator = request.user
        super().save_model(request, obj, form, change)



# Register your models here.
admin.site.register(Job,JobAdmin)

http://127.0.0.1:8000/admin/jobs/job/

在这里插入图片描述

07 | 添加自定义页面:让匿名用户可以浏览职位列表页

views.py

from django.shortcuts import render

from jobs.models import Job
from jobs.models import Cities, JobTypes

# Create your views here.
def joblist(request):
    job_list = Job.objects.order_by('job_type')
    context =  {
   
   'job_list': job_list}
    for job in job_list:
        job.city_name = Cities[job.job_city][1]
        job.type_name = JobTypes[job.job_type][1]
    return render(request, 'joblist.html', context)

template/base.html

<!--jobs/templates/base.html-->
<h1 style="margin:auto;width:50%">匠果科技开放职位</h1>

<p></p>

{
   
   % block content %}
{
   
   % endblock %}

template/joblist.html


{
   
   % extends 'base.html' %}

{
   
   % block content %}

{
   
   % if job_list %}
    <ul>
    {
   
   % for job in job_list %}
        <li>{
   
   {
   
   job.type_name}}  <a href="/job/{
   
   { job.id }}/" style="color:blue">{
   
   {
   
    job.job_name }}</a>   {
   
   {
   
   job.city_name}}  </li>
    {
   
   % endfor %}
    </ul>
{
   
   % else %}
    <p>No jobs are available.</p>
{
   
   % endif %}

{
   
   % endblock %}

recruitment/urls.py

from django.contrib import admin
from django.urls import path,include

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

jobs/urls.py

from django.urls import path
from jobs import views


urlpatterns = [
    # 职位列表
    path("joblist/", views.joblist, name="joblist"),
]

http://127.0.0.1:8000/joblist/

在这里插入图片描述

08 | 添加自定义页面:让匿名用户可以查看职位详情

template/job.html

{
   
   % extends 'base.html' %}

{
   
   % block content %}

<div style="margin:auto; width:50%;">

{
   
   % if job %}
    <div class="position_name" z>
        <h2>岗位名称:{
   
   {
   
   job.job_name}} </h2>

        城市:
        {
   
   {
   
   job.city_name}} <p></p>
    </div>
    <hr>
    <div class="position_responsibility" style="width:600px;">
        <h3>岗位职责:</h3>
        <pre style="font-size:16px">{
   
   {
   
   job.job_responsibility}}
        </pre>
    </div>
    
    <hr>
    <div class="position_requirement" style="width:600px; ">
        <h3>任职要求:</h3>
        <pre style="font-size:16px">{
   
   {
   
   job.job_requirement}}
        </pre>
    </div>

    <div class="apply_position">
        <input type="button" class="btn btn-primary" style="width:120px;" value="申请" onclick="location.href='/resume/add/?apply_position={
   
   {job.job_name}}&city={
   
   {job.city_name}}'"/>
    </div>
{
   
   % else %}
    <p>职位不存在</p>
{
   
   % endif %}

{
   
   % endblock %}
</div>

views.py

def detail(request, job_id):
    try:
        job = Job.objects.get(pk=job_id)
        job.city_name = Cities[job.job_city][1]
    except Job.DoesNotExist:
        raise Http404("Job does not exist")
    return render(request, 'job.html', {
   
   'job': job})

更新jobs/urls.py

from django.urls import path
from jobs import views


urlpatterns = [
    # 职位列表
    path("joblist/", views.joblist, name="joblist"),

    # 职位详情
    #url(r'^job/(?P<job_id>\d+)/$', views.detail, name='detail'),
    path('job/<int:job_id>/', views.detail, name='detail'),
]

在这里插入图片描述

09 | 开始一个正式的产品:产品背景、迭代思维与MVP产品规划

在这里插入图片描述

10 | 唯快不破:在产品中使用产品迭代思维

在这里插入图片描述

11 | 数据建模 & 企业级数据库设计原则

在这里插入图片描述

在这里插入图片描述

12 | 创建应用和模型,分组展示页面内容

两个需求可以合二为一:1)HR可以维护候选人信息;2)面试官可以维护面试反馈。

增加interview APP

python manage.py startapp interview
INSTALLED_APPS = [
	......
    'interview',
    ......
]

jobs/models.py

# 候选人学历
DEGREE_TYPE = ((u'本科', u'本科'), (u'硕士', u'硕士'), (u'博士', u'博士'))

interview/models.py

from django.db import models
from django.contrib.auth.models import User

from jobs.models import DEGREE_TYPE

# 第一轮面试结果
FIRST_INTERVIEW_RESULT_TYPE = ((u'建议复试', u'建议复试'), (u'待定', u'待定'), (u'放弃', u'放弃'))

# 复试面试建议
INTERVIEW_RESULT_TYPE = ((u'建议录用', u'建议录用'), (u'待定', u'待定'), (u'放弃', u'放弃'))


# HR终面结论
HR_SCORE_TYPE = (('S', 'S'), ('A', 'A'), ('B', 'B'), ('C', 'C'))


class Candidate(models.Model):
    # 基础信息
    userid = models.IntegerField(unique=True, blank=True, null=True, verbose_name=u'应聘者ID')
    username = models.CharField(max_length=135, verbose_name=u'姓名')
    city = models.CharField(max_length=135, verbose_name=u'城市')
    phone = models.CharField(max_length=135, verbose_name=u'手机号码')
    email = models.EmailField(max_length=135, blank=True, verbose_name=u'邮箱')
    apply_position = models.CharField(max_length=135, blank=True, verbose_name=u'应聘职位')
    born_address = models.CharField(max_length=135, blank=True, verbose_name=u'生源地')
    gender = models.CharField(max_length=135, blank=True, verbose_name=u'性别')
    candidate_remark = models.CharField(max_length=135, blank=True, verbose_name=u'候选人信息备注')

    # 学校与学历信息
    bachelor_school = models.CharField(max_length=135, blank=True, verbose_name=u'本科学校')
    master_school = models.CharField(max_length=135, blank=True, verbose_name=u'研究生学校')
    doctor_school = models.CharField(max_length=135, blank=True, verbose_name=u'博士生学校')
    major = models.CharField(max_length=135, blank=True, verbose_name=u'专业')
    degree = models.CharField(max_length=135, choices=DEGREE_TYPE, blank=True, verbose_name=u'学历')

    # 综合能力测评成绩,笔试测评成绩
    test_score_of_general_ability = models.DecimalField(decimal_places=1, null=True, max_digits=3, blank=True,
                                                        verbose_name=u'综合能力测评成绩')
    paper_score = models.DecimalField(decimal_places=1, null=True, max_digits=3, blank=True, verbose_name=u'笔试成绩')

    # 第一轮面试记录
    first_score = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True, verbose_name=u'初试分',
                                      help_text=u'1-5分,极优秀: >=4.5,优秀: 4-4.4,良好: 3.5-3.9,一般: 3-3.4,较差: <3分')
    first_learning_ability = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                 verbose_name=u'学习能力得分')
    first_professional_competency = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                        verbose_name=u'专业能力得分')
    first_advantage = models.TextField(max_length=1024, blank=True, verbose_name=u'优势')
    first_disadvantage = models.TextField(max_length=1024, blank=True, verbose_name=u'顾虑和不足')
    first_result = models.CharField(max_length=256, choices=FIRST_INTERVIEW_RESULT_TYPE, blank=True,
                                    verbose_name=u'初试结果')
    first_recommend_position = models.CharField(max_length=256, blank=True, verbose_name=u'推荐部门')
    first_interviewer_user = models.ForeignKey(User, related_name='first_interviewer_user', blank=True, null=True, on_delete=models.CASCADE, verbose_name=u'面试官')

    first_remark = models.CharField(max_length=135, blank=True, verbose_name=u'初试备注')

    # 第二轮面试记录
    second_score = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True, verbose_name=u'专业复试得分',
                                       help_text=u'1-5分,极优秀: >=4.5,优秀: 4-4.4,良好: 3.5-3.9,一般: 3-3.4,较差: <3分')
    second_learning_ability = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                  verbose_name=u'学习能力得分')
    second_professional_competency = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                         verbose_name=u'专业能力得分')
    second_pursue_of_excellence = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                      verbose_name=u'追求卓越得分')
    second_communication_ability = models.DecimalField(decimal_places=1, null=True, max_digits=2, blank=True,
                                                       verbose_name=u'沟通能力得分')
    second_pressure_score =
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值