#本文欢迎转载,转载请注明出处和作者
课程选课页面,会用到查询后台数据库信息并且返回给前端展示,然后前端有按钮可以点击需要选修的课程,然后返回给后台写入数据库记录。是之前08、09的两篇的实际应用案例:Python+Django网站开发系列08-JavaScript/JQuery前后端交互zhuanlan.zhihu.comPython+Django网站开发系列09-django前端展示后台数据zhuanlan.zhihu.com
1、课程选课页面展示
依然在magicbox里面选取表格组件,这次我们选择一个带按钮的表格样式,方便后面做选课,然后复制代码粘贴到stuinfo/tchinfo的html页面。(就是
{% extends 'BASE02.html' %}
{% block content %}
课程ID 课程名称 学分 上课时间 上课地点 操作{% for i in courseinfo %}
{{ i.cno }} {{ i.cname }} {{ i.ccredit }} {{ i.ctime }} {{ i.cplace }}
{% endfor %}
{% endblock %}
函数增加查询后台数据库表全部数据,并且返回给前端页面。
def selcourse(request):
courseinfo = course.objects.all()
return render_to_response('selcourse.html',locals())
效果如下:
2、按钮点击JS
2.1选课按钮业务逻辑
选课按钮的业务逻辑,有了前面的基础,就非常好弄了,与之前修改密码一样,通过JS进行编写,编写stumgrjs.js文件,增加addcourse函数。(也是通过.post向后台推送数据)
JS函数,注意也需要带参数输入,括号里面有个参数,将课程ID推送到selcourse后台函数。
function addcourse(cno) {
$.post('/selcourse/', {
'cno':cno,
}, function (res) {
if(res.result){
alert("选课成功!");
window.location.reload();
}else{
alert("选课失败!");
window.location.reload();
}
}, 'json')
}
修改selcourse业务逻辑:这里涉及ORM查询数据库操作,而且课程表(course)与学生表(course)之间是没有直接关联的,是通过中间表-成绩表(score)进行关联的,所以需要插入数据的是score表。
def selcourse(request):
if request.method == 'POST' and request.POST:
cno = request.POST['cno']
username = request.session['username']
user = student.objects.get(username=username)
sno = user.sno
score.objects.create(cno_id=cno,sno_id=sno)
result = True
return JsonResponse({'result': result})
courseinfo = course.objects.all()
return render_to_response('selcourse.html',locals())
先查询当前登录用户的sno,然后cno与sno一切写入score表,创建一条数据,注意当前score表里面的sno叫sno_id,cno叫cno_id,因为是外键引用,所以会自动改了字段名。
前端selcourse.html页面按钮编辑:与之前的onclick唯一的区别,就是调用的js函数可以带参数将'{{ i.cno }}'输入到JS函数,然后JS将cno这个id字段通过post返回给后台,这样后台就能够知道是要选修哪一门课程了。
但是当前的业务逻辑存在Bug,1是同一个的课程可以多次选修,2是每个人可以无限选修课程。需要继续优化业务逻辑。
def selcourse(request):
if request.method == 'POST' and request.POST:
cno = request.POST['cno']
username = request.session['username']
user = student.objects.get(username=username)
sno = user.sno
# 判断当前课程是否已经选修
selected = score.objects.filter(cno_id=cno,sno_id=sno)
# 技术已选课程数量,counted.count()直接统计数字
counted = score.objects.filter(sno_id=sno)
if selected:
result = '课程已选修,请勿重复选择!'
return JsonResponse({'result': result})
elif counted.count() >=2:
result = '已达到最大选修课程数量!'
return JsonResponse({'result': result})
else:
#选课成功,写入数据库
score.objects.create(cno_id=cno,sno_id=sno)
result = 'True'
return JsonResponse({'result': result})
courseinfo = course.objects.all()
return render_to_response('selcourse.html',locals())
JS代码返回的显示内容适度修改:
function addcourse(cno) {
$.post('/selcourse/', {
'cno':cno,
}, function (res) {
if(res.result=='True'){
alert("选课成功!");
window.location.reload();
}else{
alert(res.result);
window.location.reload();
}
}, 'json')
}
最终效果如下,重复选课提示已选,选修超过2门课程提示超过最大数量,选课成功提示成功。
2.2已选课程删除
同样删除按钮需要使用js向后端传输课程号,html按钮绑定delcourse的js函数,后台业务逻辑函数调用ORM的delete命令进行删除。
JS函数编辑:我们还是采用同样的.post向后台推送数据。
function delcourse(cno) {
$.post('/delcourse/', {
'cno':cno,
}, function (res) {
if(res.result=='True'){
alert("删除成功!");
window.location.reload();
}else{
alert(res.result);
window.location.reload();
}
}, 'json')
}
编辑views.py业务逻辑:单独增加一个删除函数。
def delcourse(request):
if request.method == 'POST' and request.POST:
cno = request.POST['cno']
username = request.session['username']
user = student.objects.get(username=username)
sno = user.sno
# 判断当前要删除的课程是否已选择
selected = score.objects.filter(cno_id=cno,sno_id=sno)
if selected:
score.objects.filter(cno_id=cno,sno_id=sno).delete()
result = 'True'
return JsonResponse({'result': result})
else:
#课程未选择,返回错误
result = '课程未选修,无法删除!'
return JsonResponse({'result': result})
views里面增加了函数,urls记得也要注册路由。
urlpatterns = [
......
url(r'^delcourse/', delcourse),
]
最后前端selcourse.html页面绑定到删除按钮:
最终效果如下:
3、已选课程展示
还是利用magicbox选择一个面板,拷贝代码,然后利旧一下stuinfo里面的
这里的难点有一个关联查询,因为course只有课程内容,没有授课老师,需要通过tno进行跨表连接,而student与course也没有直接联系,需要通过score中间表来进行连接,因此需要进行多表的跨表查询。
(现实生产环境的数据库表与字段比这里的数量要多得多,因此,能够达到目标查询要求的SQL语句的编写,也是数据库开发岗位日常工作的一部分。)
前端页面:stuinfo.html原来
后面继续增加面板与表格。已选课程
{% for j in selcourse %}
{{ j.score__cno }} {{ j.score__cno__cname }} {{ j.score__cno__ccredit }} {{ j.score__cno__ctime }} {{ j.score__cno__cplace}} {{ j.score__cno__tno_id__tname }}{% endfor %}
业务逻辑:
def stuinfo(request):
username = request.session['username']
userinfo = student.objects.filter(username=username)
selcourse = student.objects.filter(username=username).values('score__cno','score__cno__cname','score__cno__ccredit',
'score__cno__ctime','score__cno__cplace','score__cno__tno_id__tname')
print (selcourse)
return render_to_response('stuinfo.html',locals())
以上述为例,关联查询,首先找student表进行查询,然后与student表直接关联的表格是score表,所以后面values首先写score,然后双下划线可以直接引用score表里面的字段cno。然后通过cno可以关联到course里面的字段吗,再双下划线引用,通过course里面的tno_id字段又可以关联到teacher表,最后引用teacher表字段。
最终刷新页面效果如下: