==>数据库表:

class UserInfo(AbstractUser):
    tel = models.CharField(max_length=32, null=True, blank=True)
    gender = models.IntegerField(choices=((1, ""), (2, ""), (3, "保密")), default=1)
数据库Userinfo
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()))
数据库Customer
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
数据库Campuses
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)
数据库ClassList
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)
数据库ConsultRecord
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)
数据库Payment
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
数据库Student
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)
数据库ClassStudyRecord
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)
数据库StudentStudyRecord

==>路由分法:

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'),
    
]
URLS.PY文件

==>视图函数:

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 %}
批量添加成绩表