ModelFormset实现的一个实例
主要实现“批量录入”功能
表关系
上课记录表与学生学习记录表:
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) def __str__(self): return "{0} day{1}".format(self.class_obj, self.day_num) class StudentStudyRecord(models.Model): ''' 学生学习记录 ''' 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) student = models.ForeignKey(verbose_name="学员", to='Student', on_delete=models.CASCADE) # 与上课记录表建立外键关联 classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord", on_delete=models.CASCADE) def __str__(self): return "{0}-{1}".format(self.classstudyrecord, self.student) class Meta: unique_together=["student","classstudyrecord"]
两张表的大致关系如下:
项目大概流程
班级学习记录的模板文件如下
{% extends 'base.html' %} {% block content %} <div class="content-wrapper"> <!-- Content Header (Page header) --> <section class="content-header"> <h1> 课程记录 <small>展示</small> </h1> <ol class="breadcrumb"> <li><a href="#"><i class="fa fa-dashboard"></i> Level</a></li> <li class="active">Here</li> </ol> </section> <section class="content container-fluid"> <div class="row"> <div class="col-xs-12"> <div class="box"> <a href="" class="btn btn-primary pull-right">添加记录</a> <form action="" method="post"> {% csrf_token %} <select name="action" id="" class="form-control" style="width: 200px;display: inline-block"> <option value="batch_create">批量创建学生学习记录</option> </select> <button class="btn btn-danger" style="vertical-align: 1px;">go</button> <div class="box-body"> <table id="example2" class="table table-bordered table-hover"> <thead> <tr> <th> <input type="checkbox" id="choose"> </th> <th>序号</th> <th>班级</th> <th>节次</th> <th>老师</th> <th>本节课程标题</th> <th>学详</th> <th>操作</th> </tr> </thead> <tbody> {% for record in all_obj %} <tr> <td><input type="checkbox" name="selected_id" value="{{ record.pk }}"></td> <td>{{ forloop.counter }}</td> <td>{{ record.class_obj }}</td> <td>{{ record.day_num }}</td> <td>{{ record.teacher }}</td> <td>{{ record.course_title }}</td> <td><a href="{% url 'study_decord' record.pk %}">学详</a></td> <td> <a href="" class="btn btn-warning btn-xs">编辑</a> <a href="" class="btn btn-danger btn-xs">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> <!-- /.box-body --> </form> </div> <!-- /.box --> </div> <!-- /.col --> </div> <!-- /.row --> </section> </div> {% endblock %} {% block js %} <script> $('#choose').click(function () { var status = $(this).prop('checked'); $('[name=selected_id]').prop('checked', status); }) </script> {% endblock %}
点击“学习详情”后的路由如下
#学详路径 url(r'^study_decord/(\d+)/', views.StudyRecordDeialView.as_view(), name='study_decord'),
具体的视图函数中的处理在下面介绍:
ModelFormset的写法以及视图函数的写法
—— 这里把ModelFormset与视图函数写在一起了
#modelformset from django.forms.models import modelformset_factory from django import forms
# 这个是modelformset的写法 class StudyRecordDeialModelForm(forms.ModelForm): class Meta: model = models.StudentStudyRecord # fields = '__all__' fields = ['score','homework_note'] # 这个是批量处理学生成绩的视图函数 class StudyRecordDeialView(View): def get(self, request, class_record_id): class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) all_study_recored = models.StudentStudyRecord.objects.filter( classstudyrecord=class_record_obj, ) # 这个form_set_obj其实是一个类~工厂模式产出的一个modelformset的类 form_set_obj = modelformset_factory(model=models.StudentStudyRecord,form=StudyRecordDeialModelForm,extra=0) formset = form_set_obj(queryset=all_study_recored) return render(request, 'student/study_record_detail.html',{'formset': formset}) def post(self, request, class_record_id): class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) all_study_recored = models.StudentStudyRecord.objects.filter( classstudyrecord=class_record_obj, ) form_set_obj = modelformset_factory(model=models.StudentStudyRecord, form=StudyRecordDeialModelForm, extra=0) formset = form_set_obj(request.POST) if formset.is_valid(): formset.save() else: print(formset.errors) return redirect(reverse('study_decord',args=(class_record_id,)))
学生学习成绩批量操作前端模板渲染
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> </head> <body> <h3>录入{{ class_record_obj.class_obj }}day{{ class_record_obj.day_num }}成绩</h3> <hr> <div class="panel panel-default"> <div class="panel-heading">学习记录</div> <div class="panel-body"> <div style="width: 680px;margin: 0 auto;"> <form method="post" action=""> {% csrf_token %}
<!-- 这句话一定要加上,固定的!!! --> {{ formset.management_form }} <table class="table table-bordered"> <thead> <tr> <th>姓名</th> <th>考勤</th> <th>作业成绩</th> <th>作业评语</th> </tr> </thead> <tbody> {% for form in formset %} <tr> {{ form.id }} <td>{{ form.instance.student }}</td> {# <td>{{ form.instance.student }}</td> #} <td>{{ form.instance.get_record_display }} </td> {# <td>{{ form.instance.get_record_display }} </td> #} <td>{{ form.score }} </td> <td>{{ form.homework_note }}</td> </tr> {% endfor %} </tbody> </table> <input type="submit" value="保存"> </form> </div> </div> </div> <hr> </body> </html>
实现的效果如下