Python全栈之路-Django(五)
1 HTTP请求生命周期
请求头 -> 提取URL -> 路由关系匹配 -> 函数(模板 + 数据渲染) -> 返回给用户(响应头 + 响应体)
补充:模板渲染是在后台完成
2 老师管理(多对多)
- 需求1:添加老师信息(新URL)
- 需求2:编辑老师信息(新URL)
- 需求3:添加老师信息(Ajax)
url.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^classes/', views.classes),
url(r'^add_class/', views.add_class),
url(r'^del_class/', views.del_class),
url(r'^edit_class/', views.edit_class),
url(r'^students/', views.students),
url(r'^add_student/', views.add_student),
url(r'^del_student/', views.del_student),
url(r'^edit_student/', views.edit_student),
url(r'^modal_add_class/', views.modal_add_class),
url(r'^modal_edit_class/', views.modal_edit_class),
url(r'^modal_add_student/', views.modal_add_student),
url(r'^modal_edit_student/', views.modal_edit_student),
url(r'^teachers/', views.teachers),
url(r'^add_teacher/', views.add_teacher),
url(r'^edit_teacher/', views.edit_teacher),
url(r'^get_all_class/', views.get_all_class),
url(r'^modal_add_teacher/', views.modal_add_teacher),
]
app01.views.py
def teachers(request):
teacher_list = sqlhelper.get_list(
'select teacher.id as teacher_id,teacher.teacher_name,class.class_name \
from teacher left join teacher_class on teacher.id=teacher_class.teacher_id \
left join class on teacher_class.class_id=class.id order by teacher.id;',
[]
)
class_list = sqlhelper.get_list(
'select id as class_id,class_name from class;',
[]
)
result = {}
for item in teacher_list:
teacher_id = str(item['teacher_id'])
if teacher_id in result:
result[teacher_id]['class_name'].append(item['class_name'])
else:
result[teacher_id] = {
'teacher_id': teacher_id,
'teacher_name': item['teacher_name'],
'class_name': [item['class_name'], ]
}
return render(request, 'teachers.html', {'teacher_list': result.values(), 'class_list': class_list})
def add_teacher(request):
if request.method == 'GET':
class_list = sqlhelper.get_list(
'select id,class_name from class;',
[]
)
print(class_list)
return render(request, 'add_teacher.html', {'class_list': class_list})
elif request.method == 'POST':
teacher_name = request.POST.get('teacher_name')
class_ids = request.POST.getlist('class_ids')
print(teacher_name, class_ids)
# 老师表中添加一条数据
teacher_id = sqlhelper.create(
'insert into teacher(teacher_name) VALUES(%s);',
[teacher_name, ]
)
# 老师和班级关系表插入多条数据
# 方案1:连接多次 commit多次
# for item in class_ids:
# sqlhelper.modify(
# 'insert into teacher_class(teacher_id,class_id) VALUES(%s,%s);',
# [teacher_id, item]
# )
# 方案2:连接一次 commit多次
# obj = sqlhelper.SqlHelper()
# for item in class_ids:
# obj.modify(
# 'insert into teacher_class(teacher_id,class_id) VALUES(%s,%s);',
# [teacher_id, item]
# )
# obj.close()
# 方案3:连接一次 commit一次
temp_list = []
for item in class_ids:
temp = (teacher_id, item)
temp_list.append(temp)
obj = sqlhelper.SqlHelper()
obj.multiple_modify(
'insert into teacher_class(teacher_id,class_id) VALUES(%s,%s);',
temp_list
)
obj.close()
return redirect('/teachers/')
def edit_teacher(request):
if request.method == 'GET':
teacher_id = request.GET.get('teacher_id')
print(teacher_id)
print(type(teacher_id))
obj = sqlhelper.SqlHelper()
teacher_info = obj.get_one(
'select id,teacher_name from teacher where id=%s;',
[teacher_id, ]
)
class_id_list = obj.get_list(
'select class_id from teacher_class where teacher_id=%s',
[teacher_id, ]
)
class_list = obj.get_list(
'select id as class_id,class_name from class',
[]
)
temp_list = []
print(class_id_list)
for item in class_id_list:
temp_list.append(item['class_id'])
print(temp_list)
class_id_list = temp_list
obj.close()
return render(request,
'edit_teacher.html',
{'teacher_info': teacher_info, 'class_id_list': class_id_list, 'class_list': class_list}
)
elif request.method == 'POST':
teacher_id = request.GET.get('teacher_id')
teacher_name = request.POST.get('teacher_name')
class_ids = request.POST.getlist('class_ids')
obj = sqlhelper.SqlHelper()
# 更新老师表
obj.modify(
'update teacher set teacher_name=%s where id=%s;',
[teacher_name, teacher_id]
)
# 更新老师班级表 采用全部删除后再添加方案
# 获取老师班级对应列表
# 方式1:传统方式
# temp_list = []
# for item in class_ids:
# temp = (teacher_id, item)
# temp_list.append(temp)
# 方式2:map + lambda
temp_list = map(lambda x: (teacher_id, x), class_ids)
obj = sqlhelper.SqlHelper()
obj.modify(
'delete from teacher_class where teacher_id=%s;',
[teacher_id]
)
obj.multiple_modify(
'insert into teacher_class(teacher_id,class_id) VALUES(%s,%s);',
temp_list
)
obj.close()
return redirect('/teachers/')
def get_all_class(request):
obj = sqlhelper.SqlHelper()
class_list = obj.get_list(
'select id as class_id,class_name from class;',
[]
)
time.sleep(1)
obj.close()
return HttpResponse(json.dumps(class_list))
def modal_add_teacher(request):
ret = {'status': True, 'message': None}
try:
teacher_name = request.POST.get('teacher_name')
class_id_list = request.POST.getlist('class_id_list')
teacher_id = sqlhelper.create(
'insert into teacher(teacher_name) VALUES(%s);',
[teacher_name, ]
)
temp_list = []
for item in class_id_list:
temp = (teacher_id, item)
temp_list.append(temp)
obj = sqlhelper.SqlHelper()
obj.multiple_modify(
'insert into teacher_class(teacher_id,class_id) VALUES(%s,%s);',
temp_list
)
obj.close()
except Exception as e:
ret['status'] = False
ret['message'] = str(e)
return HttpResponse(json.dumps(ret))
template.teachers.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.shadow{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: black;
opacity: 0.3;
z-index: 999;
}
.add_modal,.edit_modal{
position: fixed;
top: 50%;
left: 50%;
width: 400px;
height: 300px;
margin-top: -150px;
margin-left: -200px;
z-index: 1000;
background-color: white;
}
.hide{
display: none;
}
.loading{
position: fixed;
width: 32px;
height: 32px;
left: 50%;
top:50%;
margin-left: -16px;
margin-top: -16px;
background-image: url("/static/images/loading.gif");
}
</style>
</head>
<body>
<h1>老师列表</h1>
<div>
<a href="/add_teacher/">添加老师</a>
<a href="#" id="btnAdd">对话框添加</a>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>老师姓名</th>
<th>任教班级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in teacher_list %}
<tr>
<td>{{ row.teacher_id }}</td>
<td>{{ row.teacher_name }}</td>
<td>
{% for item in row.class_name %}
<span style="display: inline-block;margin-right: 10px;">{{ item }}</span>
{% endfor %}
</td>
<td>
<a href="/edit_teacher/?teacher_id={{ row.teacher_id }}">编辑</a>
<a>删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="shadow hide"></div>
<div class="add_modal hide">
<p>
<input id="addTeacherName" type="text" name="teacher_name" placeholder="老师姓名">
</p>
<p>任教班级
<select multiple size="10" id="addClassIds" name="class_id">
</select>
</p>
<input id="btnAddTeacher" type="button" value="添加">
<input id="btnCancelModal" type="button" value="取消">
<span id="addErrorMsg"></span>
</div>
<div id="loading" class="loading hide"></div>
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
$(function () {
bindAdd();
bindBtnAddTeacher();
});
function bindAdd() {
$('#btnAdd').click(function () {
$('#loading').removeClass('hide');
/*
发送ajax请求,获取所有班级信息
在班级列表下拉框中生成option
*/
$.ajax({
url: '/get_all_class/',
type: 'POST',
dataType: 'JSON',
success:function (arg) {
// 将所有的数据添加到select option框
$.each(arg,function (i,row) {
$('.shadow,.add_modal').removeClass('hide')
var tag = document.createElement('option');
tag.innerHTML = row.class_name;
tag.setAttribute('value',row.class_id);
$('#addClassIds').append(tag);
})
}
})
});
$('#btnCancelModal').click(function () {
$('.shadow,.add_modal').addClass('hide')
})
}
function bindBtnAddTeacher() {
$('#btnAddTeacher').click(function () {
var teacher_name = $('#addTeacherName').val();
var class_id_list = $('#addClassIds').val();
console.log(teacher_name, class_id_list);
$.ajax({
url:'/modal_add_teacher/',
type: 'POST',
data: {'teacher_name': teacher_name,'class_id_list':class_id_list},
traditional:true, // 如果提交的数据的值有列表,则需要添加此属性
dataType: 'JSON',
success:function (arg) {
if(arg.status){
location.reload();
}else{
{# $('#addErrorMsg').innerText = arg.message;#}
alert(arg.message)
}
}
})
})
}
</script>
</body>
</html>
template.add_teacher.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加老师</h1>
<form action="/add_teacher/" method="post">
<p><input type="text" name="teacher_name" placeholder="老师姓名"></p>
<p>
<select multiple size="5" name="class_ids">
{% for row in class_list %}
<option value="{{ row.id }}">{{ row.class_name }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
template.edit_teacher.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>编辑老师</h1>
<form action="/edit_teacher/?teacher_id={{ teacher_info.id }}" method="post">
<p><input type="text" name="teacher_name" value="{{ teacher_info.teacher_name }}"></p>
<p>
<select multiple size="5" name="class_ids">
{% for row in class_list %}
{% if row.class_id in class_id_list %}
<option selected value="{{ row.class_id }}">{{ row.class_name }}</option>
{% else %}
<option value="{{ row.class_id }}">{{ row.class_name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
3 初识bootstrap
template.classes.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
{# <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css"> //压缩版本,用于生产环境#}
<style>
.hide{
display: none;
}
#shadow{
position: fixed;
left:0;
top:0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.4;
z-index: 999;
}
#modal,#editModal{
z-index: 1000;
position: fixed;
left: 50%;
top: 50%;
height: 300px;
width: 400px;
background-color: white;
margin-left: -200px;
margin-top: -150px;
}
</style>
</head>
<body>
<div style="width: 700px;margin: 0 auto;">
<h1>班级列表</h1>
<div style="margin: 10px 0;">
<a href="/add_class/" class="btn btn-primary">添加班级</a>
<a href="#" onclick="showModal();" class="btn btn-info">对话框添加</a>
</div>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>班级名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in class_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.class_name }}</td>
<td>
<a href="/del_class/?id={{ row.id }}" class="glyphicon glyphicon-trash">删除 |</a>
<a href="#" onclick="return modalEdit(this);" class="glyphicon glyphicon-pencil">对话框编辑 |</a>
<a href="/edit_class/?id={{ row.id }}" class="glyphicon glyphicon-pencil">编辑</a>
</td>
</tr>
{% endfor %}a
</tbody>
</table>
</div>
<div id="shadow" class="hide"></div>
<div id="modal" class="hide">
<form action="/modal_add_class/" method="post">
<p><input type="text" name="class_name" id="class_name"></p>
<input type="button" value="提交" onclick="AjaxSend();">
<input type="button" value="取消" onclick="cancleModal();">
<span id="errormsg"></span>
</form>
</div>
<div id="editModal" class="hide">
<h3>编辑框</h3>
<form action="/modal_add_class/" method="post">
<p><input type="text" name="class_name" id="edit_class_name"></p>
<p><input type="text" name="class_id" style="display: none" id="edit_class_id"></p>
<input type="button" value="提交" onclick="editAjaxSend();">
<input type="button" value="取消" onclick="cancleModal();">
<span id="errormsg"></span>
</form>
</div>
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
function showModal(){
document.getElementById('shadow').classList.remove('hide');
document.getElementById('modal').classList.remove('hide');
}
function cancleModal() {
document.getElementById('shadow').classList.add('hide');
document.getElementById('modal').classList.add('hide');
document.getElementById('editModal').classList.add('hide');
}
function AjaxSend() {
$.ajax({
url: '/modal_add_class/', // 提交地址
type: 'POST', // 提交方式
data: {'class_name': $('#class_name').val()}, // 提交数据
success: function (data) { // 当服务端处理完成后,返回数据时,该函数自动调用
// data 为返回的数据
if(data == 'ok'){
{# location.href='/classes/';#}
location.reload();
}else{
$('#errormsg').text(data);
}
}
})
}
function modalEdit(self) {
document.getElementById('shadow').classList.remove('hide');
document.getElementById('editModal').classList.remove('hide');
/*
1.获取当前标签
2.当前标签父标签的上方的标签
3.获取当前行班级名,放入编辑框
*/
var row = $(self).parent().prevAll();
var content = $(row[0]).text();
$('#edit_class_name').val(content);
var class_id=$(row[1]).text();
$('#edit_class_id').val(class_id)
}
function editAjaxSend() {
var class_id = $('#edit_class_id').val();
var class_name = $('#edit_class_name').val();
$.ajax({
url:'/modal_edit_class/',
type:'POST',
data: {'class_id':class_id,'class_name':class_name},
success:function (arg) {
// arg 是字符串类型
// JSON.parse(字符串) => 对象
// JSON.stringify(对象) => 字符串
arg = JSON.parse(arg);
if(arg.status){
location.reload();
}else{
alert(arg.message);
}
}
})
}
</script>
</body>
</html>