day77
day77
先做班级学习记录:
点击批量,关于学生的此次学习记录,到班级里面完成成绩的填写
url 写成多份,url路由分发
. html
+ 班级学习记录
ulrs.py
url('^class_record ''
views.py
class ClassRecordView(View):
def get(self,request):
all_obj = models.CSR.obj.all()
admin.py
study...
.....
customer文件夹
student文件夹
CSR.html
课程记录(存重复)
option 批量创建学生记录
classsr.html
td record.class_obj 对象,有str方法的话显示名字
td rec.tec 对象
{%ret_html|safe} 分页
做 1
编辑删除增加都没学下课自己写
form 批量增加学习记录
---clRV
def post(self,re)
action = request.POST.get('actionv')
select_id = request.POST.getlist('select_id')
if hasattr(self,action):
ret = getattr(self,action)(select_id)
#return redirect('url别名')
return self.get(request) 直接调用get操作减少重定向一遍
def b_c(self,select_id):
for cousr_record_id in select_id : 班级课程找属性
all_stuents = m.CSR.o.get(pk=c_r_i).class_obj.students.all()
for all()所有学生
l1 = []
for studen in all_s:
# m.SS.o.cre(stue=stu , csr_id = c_r_i )
obj = m.SS.o(stue=stu , csr_id = c_r_i )
l1.ap(obj)
多对一的写在多地里面,外键
上课记录-班级-学生-学生记录
m.S.o.bulk_create(l1)
admin.py
class ca..
list_d =
list_e =
amdin做的既可以查看和编辑
公司: 招go的比较多 学go (大型公司)
jingdong ali xinlang toutiao ali: go xuexia
京东 天猫 大型的网站 python搞起来还是比较吃力的
不是点击去编辑,而是直接就可以编辑
class StudyReDetialView(View):
def get(self,re,class_recor_id):
#找到课程记录
class_r_obj = m.ClaR.o.get(pk = cl_r_i)
# all_st = c_r_o.class_obj.students.all()
# 找到这个课程记录所生成的所有学习记录
mo.SSR.objs.fitler(classstudyrecore = c_r_i )
ret render(req,'study_record_detail.html')
学生表和客户信息表 1对1 关系 get_record_display显示元祖设置的中文
st/s_r_d.html
--url
#学详
url(r'^s_r//'',v.S.as_view(),)
moderform和form 只能生成一条表单 不能生成多条表单 同时放这一块提交
自己写
考勤:有一个系统,别人填好了
成绩:可以自己写
for choice in c_s:
option { vlaue= cho.0 selected} cho.1 默认选中
else :
html
post ‘’ 当前页面
def post(self,request):
html网页里加标识 sore_{{pk}}
data = re.Post
# data.pop('csrf')
for key,val in request.POST.items():
print(key,val) scrf : ... score_1 90 homo_note_1 111
字符串分割
field,pk = key.rsplit('_',1)
print(field,pk)
正则_数可以
错误 1
The Querydict not immable 不可修改 :深拷贝
if key = 'csrf':
continue
field,pk = key.rsplit('_',1) # score 1
models.SSR.obj.filter(pk=pk).update()
models.SSR.obj.filter(**{pk:pk}).update() 默认都是and的关系,所有的这些,因为键值对
models.SSR.obj.filter(**{pk:pk}).update(**{field:val})
所有的函数都是玩的基础,传参。。。。
return self.get(request,c_re_i)
return redirect(rever('sty_decor'),args=(clla_re_id))
需要四次循环,二个相同的update两次,效率降低
改数据结构,一次执行
{1:{‘score’ : 88,'HOmewo':'333'},
2:{‘score’ : 88,'HOmewo':'333'}}
data_dict = {}
....
if pk in data_dict :
#data_dict[pk] = {
field : val ,
}
data_dict[pk][field] = val
else:
data_dict[pk] = {
field : val ,
}
for spk,data in data_dict.items():
models.SSR.o.value(**{pk:pk}).f(**{**data})
先查后更新
如果还觉得不好,用原生sql同时执行多条语句的批量
把update给insert 相当于执行多条sql语句 并发去执行了
formset ---form
modelformset ---modelform
view.py
from django.forms.models import modelformset_factory
from django import forms
class StudyRecordDeial(View):
class Meta:
model = m.SSR
fields = '__all__'
class SRDV(View) :
def get(s,r,c):
f_s_o = modlformset_factory(model= models.SSR,form=SRDM)
queryset =
c_r_o = 表指定了
formset = form_set_obj(queryset= all_record)
修改哪条指令,queryset指定
form extra = 1 额外多一个
默认把所有的字段都加了下拉框
insatance 拿原来的值摆在这里student
显示:
record , late
get_record_display 迟到
name = 'form-1-id' 背后也是默认干切分。。。
def post(s,r,c):
forset = form_set_obj(req.POST) #
if formset.is_valid()
formset.save()
else:
print(formset.errors) 都是必填的
modelform做的验证,fields = '__all__' 是所有的
fields = ['sorce','homework_note']
区分不同的app下的,用命名空间
不会有冲突
{% url 'app01:detail' pk=12 pp=99 %}
views中的函数中使用 将app01写好
v = reverse('app01:detail', kwargs={'pk':11})
不写app_name = 'app01' 写了也得写 app01:detail
django 进阶
model进阶
QuerySet (类列表)
惰性查询
特点:
可切片
可迭代
惰性查询(modelset不会查询,什么时候用才会查询)
af_pr
models.py 表
csr : 上什么课
ssr: 学生学习记录
如何通过班级记录批量创建学生学习记录,生成一个表格形式的里面可以改内容
客户信息部分: 看总的(管理员),看有些部分的,有区分
文件夹
--templates
--customer
customer/add/
--student
生成models.py + 在admin里写添加页面(register) + admin加数据
展示班级记录,批量操作,
<td>{{ record.class_obj }}</td> #直接找到班级的对象 ——str的return值
之前的显示编辑: 得望后台去提交,而且只能提交一次(基于原生的form和modormform) 基于base页面写的页面,
<td><input type="checkbox" name="selected_id" value="{{ record.pk }}"></td>
在for循环里
request.POST.getlist(select_id 就是record_id 。。。。
<select name="action" id="" class="form-control" style="width: 200px;display: inline-block">
<option value="batch_create">批量创建学生学习记录</option>
request.POST.get(action 就是 batch_create
写函数的时候
return self.get(request) 直接掉用get方法 post了浏览器又走get方法
#减少一次中间项
models.py
default check都是默认选中的
错误1
插入了,认真
UNIQUE constraint failed: nbapp_studentstudyrecord.student_id, nbapp_studentstudyrecord.classstudyrecord_id
错误原因: 违反唯一性约束 你对表做create和update的时候对该字段的插入值重复了
错误2
把学生自定义的类给了班级
admin.site.register(models.ClassStudyRecord,StudentStudyRecordView)
对象有str方法是customer 一对一
<td>{{ studentstudyrecord.student }}</td>
(1)textarea cols 高
form action里面为空,默认当前页,提交走post
错误3
下面的两个哪个不一样,为什么一个study_record 无法匹配的到?
正常匹配得到的话,"{url 'study_record' record.pk}" 是可以点过去的
url(r'^study_record/(\d+)/', views.StudyRecordDetialView.as_view(), name='study_record '),
# url(r'^study_record/(\d+)/', views.StudyRecordDetialView.as_view(), name='study_record'),
name 第一个的多加了一个空格。。。。
print(request.POST)
# home_note = ['ddd','ddd']这样 sorce = [38,89]这样
为了方便区分那里加上了 sore_{{pk}} home_note_{{pk}} 有了区分
def get(self,request,class_record_id):
def post(self,request,class_record_id): 路径有delete/1/所以有ID
前端提交的东西 是有name=''的
for field,val in request.POST.items() : #<QueryDict: {'csrfmiddlewaretoken': ['rMxfWl8eoGMuodgpzrYxBVH0qg2TsR4Ou1tDpEWBSOqOODpZ7xMV8lNQju9P39dY'], 'score_choice_1': ['90'], 'homework_note_1': ['sdafd'], 'score_choice_2': ['85'], 'homework_note_2': ['adafs']}>
print(field,val)
'''csrfmiddlewaretoken 2BoIUok0U6IOSwj2hKoSfVR0P2Se2k1J5Qk6nH8noem8iWsCPQcgMlXQIgZaDCaT
score_choice_1 85
homework_note_1 sdafd
score_choice_2 100
homework_note_2 asdfsaf'''
(2)data_dict = {}的位置影响
data_dict = {}
for key,val in request.POST.items() :
if key == 'csrfmiddlewaretoken':
continue
field , pk = key.rsplit('_',1)
if pk in data_dict :
data_dict[pk][field] = val
else :
data_dict[pk] = {
field :val,
}
print('>>>>',data_dict)
for spk , sdata in data_dict.items():
models.StudentStudyRecord.objects.filter(**{'pk': spk}).update(**sdata)
结果显示
>>>> {'1': {'score': '100', 'homework_note': '真是个好孩子大阿斯顿发生按地方撒法师阿斯顿发'}, '2': {'score': '90', 'homework_note': 'asdad按地方撒'}}
for key,val in request.POST.items() :
if key == 'csrfmiddlewaretoken':
continue
field , pk = key.rsplit('_',1)
data_dict = {}
if pk in data_dict :
data_dict[pk][field] = val
else :
data_dict[pk] = {
field :val,
}
print('>>>>',data_dict)
for spk , sdata in data_dict.items():
models.StudentStudyRecord.objects.filter(**{'pk': spk}).update(**sdata)
结果显示
>>>> {'1': {'score': '100'}}
>>>> {'1': {'homework_note': '真是个好孩子大按地方撒法师阿斯顿发'}}
>>>> {'2': {'homework_note': 'asdad按地方撒'}}
(3)第一种效率低的做法,效率低吗,不大好看是真吧
def post(self,request,class_record_id):
print(request.POST) # home_note = ['ddd','ddd']这样 sorce = [38,89]这样 为了方便区分那里加上了
class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) #课程记录
# class_record_obj.class_obj.students.all() #所有的学生
all_study_records = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
#关联了课程记录 class——record-id
classstudyrecord=class_record_obj,
)
score_choices = models.StudentStudyRecord.score_choices #类的属性
for key,val in request.POST.items() : #<QueryDict: {'csrfmiddlewaretoken': ['rMxfWl8eoGMuodgpzrYxBVH0qg2TsR4Ou1tDpEWBSOqOODpZ7xMV8lNQju9P39dY'], 'score_choice_1': ['90'], 'homework_note_1': ['sdafd'], 'score_choice_2': ['85'], 'homework_note_2': ['adafs']}>
print(key,val)
'''csrfmiddlewaretoken 2BoIUok0U6IOSwj2hKoSfVR0P2Se2k1J5Qk6nH8noem8iWsCPQcgMlXQIgZaDCaT
score_choice_1 85
homework_note_1 sdafd
score_choice_2 100
homework_note_2 asdfsaf'''
if key == 'csrfmiddlewaretoken':
continue
field , pk = key.rsplit('_',1) # score_choice_1 85 --> score_choice 85
print(field,pk)
# models.StudentStudyRecord.objects.filter(pk=pk).update()
models.StudentStudyRecord.objects.filter(**{'pk': pk}).update(**{field:val})
# 打散传参和上面的情况一样,只不过是和的关系 但是注意这里是 ** 'pk' 不是**{pk:pk}
# return render(request,'student/study_record_detail.html',{'class_record_obj':class_record_obj,
# 'score_choices':score_choices,'all_study_records': all_study_records })
# return self.get(request,class_record_id)
return redirect( reverse('study_record',args=(class_record_id,)))
formset
models.py
default 是已签到,= checked 默认值
def get()
formset 有个参数 点进去 有个extra=1多一行了
html
{{ formset.management_form }} {# 类似于csrf认识的标识符 #}
<table class="table table-bordered">
<thread>
<tr>
<th>姓名</th>
<th>考勤</th>
<th>作业成绩</th>
<th>作业评语</th>
</tr>
</thread>
<tbody>
{% for form in formset %} {# formset 就包括了一条条记录#}
<tr>
{{ form.id }} {# pk值#}
<td>{{ form.student }}</td> {#默认会自动生成下拉框 ,如果不让他渲染,#}
{#那么需要使用form.instance.student.这是form对象原值,原来的数据#}
<td>{{ form.get_record_display }}</td>
{# <td>{{ form.instance.get_record_display }}</td>#}
<td>{{ form.score }}</td>
<td>{{ form.homework_note }}</td>
</tr>
{% endfor %}
extra =1 错误3
加了的值
给这个N/A 后边的评语加值了 。。。
NOT NULL constraint failed: nbapp_studentstudyrecord.classstudyrecord_id
非空约束失败:nbapp_studentstudyrecord.classstudyrecord_id
错误4
get和post的不一样
def get():
form_set_obj(query= all_study_record)
def post():
form_set_obj(request.POST)
formset 使用
from django.forms.models import modelformset_factory
from django import forms
class StudyRecordDetialModelForm(forms.ModelForm):
class Meta:
model = models.StudentStudyRecord
# fields = '__all__'
fields = ['score','homework_note']
class StudyRecordDetialView2(View):
def get(self,request,class_record_id):
all_study_record = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
classstudyrecord=class_record_id,
)
form_set_obj = modelformset_factory(model=models.StudentStudyRecord,form=StudyRecordDetialModelForm)
# 哪张表(model)来使用modelformset 使用这张表来加工表的时候用的哪个modermform(from)
formset = form_set_obj(queryset = all_study_record) #使用all_study_record来加工query记录
# 来加工modermform的哪些数据,通过queryset来指定
return render(request, 'student/study_record_detail.html', { 'formset': formset })
def post(self,request,class_record_id):
all_study_record = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
classstudyrecord=class_record_id,
)
form_set_obj = modelformset_factory(model=models.StudentStudyRecord, form=StudyRecordDetialModelForm,extra=0)
# 哪张表(model)来使用modelformset 使用这张表来加工表的时候用的哪个modermform(from)
formset = form_set_obj(request.POST) # 使用all_study_record来加工query记录
# 来加工modermform的哪些数据,通过queryset来指定
if formset.is_valid():
formset.save()
else:
print(formset.errors)
#
# return redirect(reverse('study_record',args=(class_record_id,)))
return self.get(request,class_record_id)
# return request.get(request,class_record_id)
在课程页面批量创建多个学生记录
class ClassRecordView(View):
def get(self,request):
all_obj = models.ClassStudyRecord.objects.all()
return render(request,'student/class_study_record.html',{'all_obj':all_obj})
def post(self,request):
action = request.POST.get('action')
selected_id = request.POST.getlist('selected_id')
if hasattr(self,action):
ret = getattr(self,action)(selected_id) #()对应创建的id
# return redirect()
return self.get(request)
def batch_create(self,selected_id):
#班级记录 管理班级 找student找不到 找s再找ssr
for course_record_id in selected_id:
all_students = models.ClassStudyRecord.objects.get(pk=course_record_id).class_obj.students.all() #record_id 是all_obj的CSR的id
#不写的话写student.set__all() #关联的students relate_name 代替类名小写
#多对一的关系,外键是写在了多的表里,多的表找属性
l1 = []
for student in all_students: # 小黑 梨花
# models.StudentStudyRecord.objects.create(student=student,classstudyrecord_id=course_record_id)
# 2 批量创建
obj = models.StudentStudyRecord(student=student,classstudyrecord_id=course_record_id)
l1.append(obj)
models.StudentStudyRecord.objects.bulk_create(l1)
在一个页面展示修改提交到后台保存
版本一 post 多次提交
class StudyRecordDetialView(View):
def get(self,request,class_record_id):
class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) #课程记录
# class_record_obj.class_obj.students.all() #所有的学生
all_study_records = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
#关联了课程记录 class——record-id
classstudyrecord=class_record_obj,
)
score_choices = models.StudentStudyRecord.score_choices #类的属性
return render(request,'student/study_record_detail.html',{'class_record_obj':class_record_obj,
'score_choices':score_choices,'all_study_records': all_study_records })
def post(self,request,class_record_id):
print(request.POST) # home_note = ['ddd','ddd']这样 sorce = [38,89]这样 为了方便区分那里加上了
class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) #课程记录
# class_record_obj.class_obj.students.all() #所有的学生
all_study_records = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
#关联了课程记录 class——record-id
classstudyrecord=class_record_obj,
)
score_choices = models.StudentStudyRecord.score_choices #类的属性
for key,val in request.POST.items() : #<QueryDict: {'csrfmiddlewaretoken': ['rMxfWl8eoGMuodgpzrYxBVH0qg2TsR4Ou1tDpEWBSOqOODpZ7xMV8lNQju9P39dY'], 'score_choice_1': ['90'], 'homework_note_1': ['sdafd'], 'score_choice_2': ['85'], 'homework_note_2': ['adafs']}>
print(key,val)
'''csrfmiddlewaretoken 2BoIUok0U6IOSwj2hKoSfVR0P2Se2k1J5Qk6nH8noem8iWsCPQcgMlXQIgZaDCaT
score_choice_1 85
homework_note_1 sdafd
score_choice_2 100
homework_note_2 asdfsaf'''
if key == 'csrfmiddlewaretoken':
continue
field , pk = key.rsplit('_',1) # score_choice_1 85 --> score_choice 85
print(field,pk)
# models.StudentStudyRecord.objects.filter(pk=pk).update()
models.StudentStudyRecord.objects.filter(**{'pk': pk}).update(**{field:val})
# 打散传参和上面的情况一样,只不过是和的关系 但是注意这里是 ** 'pk' 不是**{pk:pk}
# return render(request,'student/study_record_detail.html',{'class_record_obj':class_record_obj,
# 'score_choices':score_choices,'all_study_records': all_study_records })
# return self.get(request,class_record_id)
return redirect( reverse('study_record',args=(class_record_id,)))
版本二 提升效率 设计数据结构
# 为了节省 两个更新
def post(self,request,class_record_id):
print(request.POST) # home_note = ['ddd','ddd']这样 sorce = [38,89]这样 为了方便区分那里加上了
class_record_obj = models.ClassStudyRecord.objects.get(pk=class_record_id) #课程记录
# class_record_obj.class_obj.students.all() #所有的学生
all_study_records = models.StudentStudyRecord.objects.filter( # 找到这个课程记录的所有学生记录
#关联了课程记录 class——record-id
classstudyrecord=class_record_obj,
)
'''
{
1 : {'score':85,'homework_not':'33',
2 : {'score':85,'homework_not':'33',
}
'''
score_choices = models.StudentStudyRecord.score_choices #类的属性
data_dict = {}
for key,val in request.POST.items() : #<QueryDict: {'csrfmiddlewaretoken': ['rMxfWl8eoGMuodgpzrYxBVH0qg2TsR4Ou1tDpEWBSOqOODpZ7xMV8lNQju9P39dY'], 'score_choice_1': ['90'], 'homework_note_1': ['sdafd'], 'score_choice_2': ['85'], 'homework_note_2': ['adafs']}>
print(key,val)
if key == 'csrfmiddlewaretoken':
continue
field , pk = key.rsplit('_',1) # score_choice_1 85 --> score_choice 85
if pk in data_dict :
data_dict[pk][field] = val
else :
data_dict[pk] = {
field :val,
}
print('>>>>',data_dict)
for spk , sdata in data_dict.items():
models.StudentStudyRecord.objects.filter(**{'pk': spk}).update(**sdata)
# 打散传参和上面的情况一样,只不过是和的关系 但是注意这里是 ** 'pk' 不是**{pk:pk}
# return render(request,'student/study_record_detail.html',{'class_record_obj':class_record_obj,
# 'score_choices':score_choices,'all_study_records': all_study_records })
# return self.get(request,class_record_id)
return redirect( reverse('study_record',args=(class_record_id,)))
class_study_record.html
<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>
<!-- /.box-header -->
<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>
{# <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_record' record.pk %}">学详</a></td>#}
<td><a href="{% url 'study_record' record.pk %}">学详</a></td>
<td>
<a href="" class="btn btn-warning btn-xs">编辑</a>
<a href="" class="btn btn-danger btn-xs">删除</a>
</td>
{# <td>{{ customer.get_classlist }}</td>#}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</form>
</div>
<!-- /.box -->
</div>
<!-- /.col -->