==>数据库表:
class UserInfo(AbstractUser): tel = models.CharField(max_length=32, null=True, blank=True) gender = models.IntegerField(choices=((1, "男"), (2, "女"), (3, "保密")), default=1)
class_type_choices = (('fulltime', '脱产班',), ('online', '网络班'), ('weekend', '周末班',),) source_type = (('qq', "qq群"), ('referral', "内部转介绍"), ('website', "官方网站"), ('baidu_ads', "百度推广"), ('office_direct', "直接上门"), ('WoM', "口碑"), ('public_class', "公开课"), ('website_luffy', "路飞官网"), ('others', "其它"),) course_choices = (('LinuxL', 'Linux中高级'), ('PythonFullStack', 'Python高级全栈开发'),) enroll_status_choices = (('signed', "已报名"), ('unregistered', "未报名"), ('studying', '学习中'), ('paid_in_full', "学费已交齐")) seek_status_choices = (('A', '近期无报名计划'), ('B', '1个月内报名'), ('C', '2周内报名'), ('D', '1周内报名'), ('E', '定金'), ('F', '到班'), ('G', '全款'), ('H', '无效'),) pay_type_choices = (('deposit', "订金/报名费"), ('tuition', "学费"), ('transfer', "转班"), ('dropout', "退学"), ('refund', "退款"),) attendance_choices = (('checked', "已签到"), ('vacate', "请假"), ('late', "迟到"), ('absence', "缺勤"), ('leave_early', "早退"),) score_choices = ((100, 'A+'), (90, 'A'), (85, 'B+'), (80, 'B'), (70, 'B-'), (60, 'C+'), (50, 'C'), (40, 'C-'), (0, ' D'), (-1, 'N/A'), (-100, 'COPY'), (-1000, 'FAIL'),) class Customer(models.Model): qq = models.CharField('QQ', max_length=64, unique=True, help_text='QQ号必须唯一') qq_name = models.CharField('QQ昵称', max_length=64, blank=True, null=True) name = models.CharField('姓名', max_length=32, blank=True, null=True, help_text='学员报名后,请改为真实姓名') sex_type = (('male', '男'), ('female', '女')) sex = models.CharField("性别", choices=sex_type, max_length=16, default='male', blank=True, null=True) birthday = models.DateField('出生日期', default=None, help_text="格式yyyy-mm-dd", blank=True, null=True) phone = models.BigIntegerField('手机号', blank=True, null=True) source = models.CharField('客户来源', max_length=64, choices=source_type, default='qq') introduce_from = models.ForeignKey('Customer', verbose_name="转介绍自学员", blank=True, null=True, on_delete=models.CASCADE) course = MultiSelectField("咨询课程", choices=course_choices) class_type = models.CharField("班级类型", max_length=64, choices=class_type_choices, default='fulltime') customer_note = models.TextField("客户备注", blank=True, null=True, ) status = models.CharField("状态", choices=enroll_status_choices, max_length=64, default="unregistered", help_text="选择客户此时的状态") date = models.DateTimeField("咨询日期", auto_now_add=True) last_consult_date = models.DateField("最后跟进日期", auto_now_add=True) next_date = models.DateField("预计再次跟进时间", blank=True, null=True) consultant = models.ForeignKey('UserInfo', verbose_name="销售", related_name='customers', blank=True, null=True, on_delete=models.CASCADE) class_list = models.ManyToManyField('ClassList', verbose_name="已报班级", ) age = models.CharField(verbose_name='年龄', max_length=32, blank=True, null=True) email = models.EmailField(verbose_name='邮箱', max_length=32, blank=True, null=True) company = models.CharField(verbose_name='公司', max_length=32, blank=True, null=True) def __str__(self): return self.name + ":" + self.qq def get_classlist(self): l = [] for cls in self.class_list.all(): l.append(str(cls)) return mark_safe(",".join(l)) def get_status(self): status_color = { "studying": "green", "signed": "#B03060", "unregistered": "red", "paid_in_full": "blue" } return mark_safe("<span style='background-color:%s;color:white'>%s</span>" % ( status_color[self.status], self.get_status_display()))
class Campuses(models.Model): name = models.CharField(verbose_name='校区', max_length=64) address = models.CharField(verbose_name='详细地址', max_length=512, blank=True, null=True) def __str__(self): return self.name
class ClassList(models.Model): course = models.CharField("课程名称", max_length=64, choices=course_choices) semester = models.IntegerField("学期") campuses = models.ForeignKey('Campuses', verbose_name="校区", on_delete=models.CASCADE) price = models.IntegerField("学费", default=10000) memo = models.CharField('说明', blank=True, null=True, max_length=100) start_date = models.DateField("开班日期") graduate_date = models.DateField("结业日期", blank=True, null=True) # contract = models.ForeignKey('ContractTemplate', verbose_name="选择合同模版", blank=True, null=True,on_delete=models.CASCADE) teachers = models.ManyToManyField('UserInfo', verbose_name="老师") class_type = models.CharField(choices=class_type_choices, max_length=64, verbose_name='班额及类型', blank=True, null=True) class Meta: unique_together = ("course", "semester", 'campuses') def __str__(self): return "{}{}({})".format(self.get_course_display(), self.semester, self.campuses)
class ConsultRecord(models.Model): customer = models.ForeignKey('Customer', verbose_name="所咨询客户", on_delete=models.CASCADE) note = models.TextField(verbose_name="跟进内容...") status = models.CharField("跟进状态", max_length=8, choices=seek_status_choices, help_text="选择客户此时的状态") consultant = models.ForeignKey("UserInfo", verbose_name="跟进人", related_name='records', on_delete=models.CASCADE) date = models.DateTimeField("跟进日期", auto_now_add=True) delete_status = models.BooleanField(verbose_name='删除状态', default=False) def __str__(self): return str(self.customer) + str(self.consultant)
class Payment(models.Model): customer = models.ForeignKey(verbose_name='关联客户', to='Customer', on_delete=models.CASCADE) money = models.IntegerField(verbose_name='付费金额') create_time = models.DateTimeField(verbose_name='付费时间', auto_now_add=True)
class Student(models.Model): customer = models.OneToOneField(verbose_name='客户信息', to='Customer', on_delete=models.CASCADE, null=True, blank=True) class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True) emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人') company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True) location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True) position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True) salary = models.IntegerField(verbose_name='薪资', blank=True, null=True) welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True) date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True) memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True) class Meta: verbose_name_plural = '学员表' verbose_name = '学员表' def __str__(self): return self.customer.qq_name
class ClassStudyRecord(models.Model): class_obj = models.ForeignKey(verbose_name="班级", to="ClassList", on_delete=models.CASCADE) day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字") teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo', on_delete=models.CASCADE) date = models.DateField(verbose_name="上课日期", auto_now_add=True) course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True) course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True) has_homework = models.BooleanField(default=True, verbose_name="本节有作业") homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True) homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True) exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True) class Meta: verbose_name_plural = '上课记录表' verbose_name = '上课记录表' def __str__(self): return "{0} day{1}".format(self.class_obj, self.day_num)
class StudentStudyRecord(models.Model): student = models.ForeignKey(verbose_name="学员", to='Student', on_delete=models.CASCADE) classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord", on_delete=models.CASCADE) record_choices = (('checked', "已签到"), ('vacate', "请假"), ('late', "迟到"), ('noshow', "缺勤"), ('leave_early', "早退"), ) record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64) score_choices = ((100, 'A+'), (90, 'A'), (85, 'B+'), (80, 'B'), (70, 'B-'), (60, 'C+'), (50, 'C'), (40, 'C-'), (0, ' D'), (-1, 'N/A'), (-100, 'COPY'), (-1000, 'FAIL'), ) score = models.IntegerField("本节成绩", choices=score_choices, default=-1) homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True) note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True) homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None) stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True) date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True) class Meta: verbose_name_plural = '学生学习记录表' verbose_name = '学生学习记录表' unique_together=["student","classstudyrecord"] def __str__(self): return "{0}-{1}".format(self.classstudyrecord, self.student)
==>路由分法:
from django.urls import re_path from rbac.views import student, class_study_record, student_study_record urlpatterns = [ re_path(r'^class_study_record/list/$', class_study_record.class_study_record_list,name='class_study_record_list'), re_path(r'^student_study_record/list/$', student_study_record.student_study_record_list,name='student_study_record_list'), re_path(r'^score_record/(\d+)/$', class_study_record.score_record,name='score_record'), ]
==>视图函数:
def class_study_record_list(request): if request.method == 'GET': # 获取所有班级学习记录 class_study_records = ClassStudyRecord.objects.all() print(class_study_records) # 返回到列表展示页 return render(request, 'class_study_record_list.html', {"class_study_records": class_study_records}) else: # 获取要批量添加学生记录的班级记录表id selected_pk_list = request.POST.getlist('selected_pk_list') print(selected_pk_list) # 可能会是选多个,所以要循环 for class_study_record_pk in selected_pk_list: # 通过班级记录表pk,找到这个班级对应的学生 # ClassStudyRecord--> student_list = ClassStudyRecord.objects.filter(pk=class_study_record_pk).values('class_obj__student') for student in student_list: try: StudentStudyRecord.objects.create(student_id=student['class_obj__student'], classstudyrecord_id=class_study_record_pk) except Exception: pass return render(request, 'class_study_record_list.html')
def score_record(request, class_study_record_id=None): if request.method == 'GET': # 通过上课记录 class_study_record_obj = ClassStudyRecord.objects.get(pk=class_study_record_id) student_study_record_list = class_study_record_obj.studentstudyrecord_set.all() score_choices = StudentStudyRecord.score_choices return render(request, 'score_record.html',locals()) else: data_dict = {} for key, val in request.POST.items(): if key == "csrfmiddlewaretoken": continue field, pk = key.rsplit('_', 1) if pk not in data_dict: data_dict[pk] = {field: val} else: data_dict[pk][field] = val print(data_dict) for pk, data in data_dict.items(): StudentStudyRecord.objects.filter(pk=pk).update(**data) return redirect(request.path)
==>网页模板:
{% extends 'base.html' %} {% block content_main %} <!-- Main content --> <section class="content container-fluid"> <form action="" method="post"> {% csrf_token %} <div class="row"> <div class="col-lg-6"> <label for="action_id"></label> <select id="action_id" class="form-control"> <option>请选择操作......</option> <option>批量录入学生成绩</option> </select> </div><!-- /.col-lg-6 --> <div class="col-lg-6"> <span class="input-group-btn"> <button class="btn btn-success btn-md" type="submit">Go!</button> </span> </div><!-- /.col-lg-6 --> </div><!-- /.row --> <table class="table table-bordered table-hover"> <thead> <tr> <td> <label for="checkbox_id"></label> <input type="checkbox" id="checkbox_id"> </td> <td>班级</td> <td>节次</td> <td>讲师</td> <td>上课时间</td> <td>本节课程标题</td> <td>本节课程内容概要</td> <td>录入成绩</td> <td>编辑</td> <td>删除</td> </tr> </thead> <tbody> {% for class_study_record in class_study_records %} <tr> <td> <label for="selected_pk_list"></label> <input type="checkbox" id="selected_pk_list" name="selected_pk_list" value="{{ class_study_record.pk }}"> </td> <td>{{ class_study_record.class_obj }}</td> <td>{{ class_study_record.day_num }}</td> <td>{{ class_study_record.teacher }}</td> <td>{{ class_study_record.date|date:'Y-m-d' }}</td> <td>{{ class_study_record.course_title }}</td> <td>{{ class_study_record.course_memo }}</td> <td><a href="{% url 'score_record' class_study_record.pk %}">录入成绩</a></td> <td><a href="">编辑</a></td> <td><a href="">删除</a></td> </tr> {% endfor %} </tbody> </table> </form> </section> {% endblock %}
{% extends 'base.html' %} {% block content_main %} <!-- Main content --> <section class="content container-fluid"> <h3>录入{{ class_study_record_obj.class_obj }}(day{{ class_study_record_obj.day_num }})成绩</h3> <form action="" method="post"> {% csrf_token %} <table class="table table-hover table-bordered"> <thead> <tr> <th>编号</th> <th>姓名</th> <th>考勤</th> <th>成绩</th> <th>批语</th> </tr> </thead> <tbody> {% for studentstudyrecord in student_study_record_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ studentstudyrecord.student }}</td> <td>{{ studentstudyrecord.get_record_display }}</td> <td> <select name="score_{{ studentstudyrecord.pk }}" id=""> {% for score_choice in score_choices %} {% if studentstudyrecord.score == score_choice.0 %} <option selected value="{{ score_choice.0 }}">{{ score_choice.1 }}</option> {% else %} <option value="{{ score_choice.0 }}">{{ score_choice.1 }}</option> {% endif %} {% endfor %} </select> </td> <td> <input type="text" placeholder="批语" name="homework_note_{{ studentstudyrecord.pk }}" class="form-control" value="{{ studentstudyrecord.homework_note }}"> </td> </tr> {% endfor %} </tbody> </table> <input type="submit" class="btn btn-success pull-right" value="保存"> </form> </section> {% endblock %}