在这里我们想要直接使用学生那个表来存放账号密码,如果这个学生没有账号密码,就默认其账号密码是他的学号。所以,我们需要给学生表加上两个字段
- 在stu/models 文件里添加下面代码, 在migrate数据迁移
s_username = models.CharField(max_length=30, null=True)
s_password = models.CharField(max_length=256, null=True)
alter table student add s_username varchar(30) default null;
alter table student add s_password varchar(256) default null;
创建一个uauth的app, 其实你也可以不用创建,用在之前创建的其他app中也行
实现登录的后台方法:
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
username = request.POST.get('name')
password = request.POST.get('password')
role = request.POST.get('role')
# 如果登录身份是学生的话,可以进行两次判断,首先判断是否存在usernam, 在判断默认账号密码
if role == 'student':
if Student.objects.filter(s_username=username).exists():
stu = Student.objects.filter(s_username=username).first()
if check_password(password, stu.s_password):
request.session['s_name'] = stu.s_name
return HttpResponse('/stu/group')
else:
return render(request, 'login.html', {'message': '用户名不存在!'})
else:
if Student.objects.filter(s_num=username).exists():
stu = Student.objects.filter(s_num=username)
if stu[0].s_num == password:
request.session['s_name'] = stu[0].s_name
return HttpResponseRedirect('/stu/group')
else:
return render(request, 'login.html', {'message': '用户名不存在!'})
else:
return render(request, 'login.html', {'message': '用户名不存在!'})
真正意义上的注册功能,在这个系统中其实是不存在的,我的想法是,每新添加一个学生,这个系统就新增一个用户,这个用户可以以他的学号为默认的账号密码,进行登陆学生选课查询系统,在系统进行口令更改
def change_admin(request):
"""更改口令"""
if request.method == 'GET':
return render(request, 'register.html')
if request.method == 'POST':
s_name = request.session['s_name']
if s_name:
username = request.POST.get('username')
password = request.POST.get('password')
stu = Student.objects.get(s_name=s_name)
stu.s_username = username
stu.s_password = make_password(password)
stu.save()
return HttpResponseRedirect('')
在这里面使用了django自带的表django_session来存放登录信息,不过目前其实只是为了简便所以没有使用太过复杂的操作。
中间件使用了一种面向切面的方式,写好中间件之后,直接进行settings
的配置,可以在每次跳转页面的时候进行一次,是否登录的判断,没有登录就跳转到登录页面
这一部分在这里略过,下一篇文章中我会画时间详细介绍,因为在这个部分中有很多容易出现的坑。
要想实现学生选课,每个学生可以对应多门课程, 每门课程也可以对应对个学生, 所以学生和课程的对应关系为多对多,在数据库表格添加时需要多建立一个中间表,这个中间表存在两个外键分别对应学生与课程表。
使用mysql语句的话就是在创建一个表格
create table student_c(
id int not noll auto-increment,
student_id int default null,
course_id int default null,
foreign key(student_id) references student(id),
foreign key(course_id) references course(id)
)
而使用Django自带的创建表格的方法,只需在Student类里面,添加下面的一段代码,在进行数据迁移即可,(注意:不要动migrations文件里面的东西, 否则有可能error):
c = models.ManytoManyField(Course, null=True, blank=True)
还是用到的前面所使用的block站位法,把头部与尾部写在模板页面中会少简单很多,在这里就不再给出实现代码了,只给出效果
在管理员进行了学生的添加后,初始默认可以使用学号作为账号密码进行登录,通过不同的身份验证来进行跳转,学生可以跳转到学生选课系统,管理员可以跳转到管理后台系统。
当然,在学生选课功能中肯定需要先实现显示所有课程。显示所有课程的方法前面也已经讲过了,不再重复。
在之后,其实Django本身也有已经封装好的增删改查的操作,在写这个功能时,我将不再使用原始方法来慢慢实现增删改查。其次在使用这个方法的同时,我还将使用到一个web中,十分重要的技术————ajax
目前是显示选课的所有课程的信息,这个页面是通过一个模拟的登录界面进来的,里面存放了当前学生的信息
选课方法:
def sure_choice(request):
"""确认选择"""
if request.method == 'GET':
course_id = request.GET.get('course_id')
s_name = request.session['s_name']
if s_name:
stu = Student.objects.get(s_name=s_name)
course = Course.objects.get(pk=course_id)
if stu.c.all().exists():
return HttpResponseRedirect('/course/choicecourse')
else:
stu.c.add(course)
return HttpResponseRedirect('/course/choicecourse')
主要实现点击选择链接便可以直接选择该门课程。
在实现过程中出了点问题,导致一些数据被我删掉了,但是功能并没影响
既然有选课功能,在选课的时候手贱了,肯定也可以取消所选的课程
取消选课:
def cancle(request):
"""取消选择"""
if request.method == 'GET':
course_id = request.GET.get('course_id')
course = Course.objects.get(id=course_id)
s_name = request.session['s_name']
stu = Student.objects.get(s_name=s_name)
stu.c.remove(course)
return HttpResponseRedirect('/course/choicecourse')
在进行选课操作的时候这个部分是完全可以使用ajax异步获取的方式来进行点击后显示选课信息。下面将介绍的是通过ajax来获取数据的方法
选课接口:
def ajax_choice(request):
if request.method == 'GET':
data = {
'msg': '请求成功!',
'coding': 200
}
course_id = request.GET.get('course_id')
s_name = request.session['s_name']
if s_name:
stu = Student.objects.get(s_name=s_name)
course = Course.objects.get(pk=course_id)
if stu.c.all().exists():
data['msg'] = '已经选课该课程!'
else:
stu.c.add(course)
courses = stu.c.all()
courses = serializers.serialize('json', courses)
data['courses'] = courses
return JsonResponse(data)
页面ajax获取数据:
function choice(course_id){
$.ajax({
type: 'get',
dataType: 'json',
url: '/course/ajaxchoice/',
data: {'course_id': course_id},
error: function (msg) {
console.log('请求错误!')
},
success: function (msg) {
courses = JSON.parse(msg.courses);
console.log(msg);
$('#choiceinfo').empty();
for(var i = 0; i < courses.length; i++){
s = courses[i].fields.c_name + '')">取消 | ';
$('#choiceinfo').append(s)
}
}
})
}
取消选课:
def ajax_cancle(request):
if request.method == 'GET':
data = {
'msg': '请求成功!',
'coding': 200
}
courselist = []
course_id = request.GET.get('course_id')
course = Course.objects.get(id=course_id)
s_name = request.session['s_name']
if s_name:
stu = Student.objects.get(s_name=s_name)
stu.c.remove(course)
courses = stu.c.all()
for course in courses:
dict1 = {}
dict1['c_name'] = course.c_name
dict1['c_id'] = course.id
courselist.append(dict1)
data['courses'] = courselist
return JsonResponse(data)
取消和选择两个接口所使用的到的ajax基本上是大致相同的,所以我不在列出取消选课的ajax方法。
注意,在上面为了介绍一种序列化对象的方式,使用了django.core 中的serializers库,不是rest framework中的库,但是这样序列化出来的数据是一个字符串,在ajax中接收到数据之后还需要通过JSON.parse转化成Json格式。
以上容易遇见的坑是,大家使用序列化之后,一定要打个断点,检查一下他最终的到的数据到底是什么!