整個頁面的效果如下圖所示
1、登陸注冊頁面

2、注冊的頁面

3、登陸頁面

4、所有設備

5、正常設備頁面

6、退庫設備頁面

7、丟失設備頁面

8、導出設備的頁面,僅僅在所有設備頁面才支持導出按鈕

9、添加設備頁面

10、編輯設備的頁面


11、刪除設備頁面

上面就是我做的資產管理系統的所有的頁面
下面我們按照頁面來分析代碼
一、登陸頁面
頁面的總體布局初始狀態是2個框,一個用來登陸,一個用來注冊,由於注冊很簡單,我們先把注冊梳理一下
<div id="home">
<input type="button" value="注冊" id="register">
<input type="button" value="登陸" id="login">
</div>
這個div的id是home,我們來看下home的css樣式
#home{
position: fixed;
left: 50%;
top: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
}
設置為固定模式,為了讓框居中,首先讓整個div的距離左邊50%,距離頂部50%,由於這個距離左邊50%實現的效果是左邊框距離左邊的距離占整個屏幕的50%,為了讓整個框居中,我們還需要讓整個框向左邊移動框的寬度的50%,也就是margin-left:-150px,通過樣式上下的距離也是一樣的,這里實現整個div標簽居中顯示
我們看到注冊的input標簽的id為register,我們為這個標簽綁定了click事件,下面我們來看下這個jquery函數是怎么寫的
function bind_register_func() {
$("#register").bind("click",function () {
$("#error_register").html("");
$("#register_form").removeClass("hide");
$("#shade").removeClass("hide");
})
}
為id為register這個標簽綁定了一個click事件,點擊這個標簽就會執行這個函數
這個函數有2個作用
作用1:
首先把id為error_register標簽的值清空,因為如果是上次注冊有報錯的話,這次再次點擊這里還是會顯示錯誤信息,所以這里需要先把賦值清空,用html("")是清空內容,如果在括號中有值,則是賦值的意思
作用2:
這里我們又用到模態對話框,點擊按鈕,會把注冊的框hide的class移除,用removeclass("hide")移除hide屬性,這里我們看下hide的css屬性是什么
.hide{
display: none;
}
display:None就是這個標簽不顯示,我們移除這個屬性,則標簽就會顯示出來,下面我們來看下顯示出來的2個標簽
<div class="hide modal" id="register_form">
<form action="/zhaoshebei/form_register/" method="post">
<p><label for="register_username">用戶:</label><input type="text" placeholder="姓名工號" name="user_name" id="register_username"></p>
<p><label for="register_userpwd">密碼:</label><input type="password" placeholder="密碼" name="user_pwd" id="register_userpwd"></p>
<p><span id="error_register"></span></p>
<input type="button" value="注冊" id="ajax_register">
<input type="reset" value="重置">
<input type="button" value="取消" class="del_register_form">
</form>
</div>
<div class="hide shade" id="shade">
</div>
shade主要是起遮罩的作用,放在下面,遮罩整個的頁面,真正的頁面是在register_form標簽中,放在遮罩層的上面
下面我們重點看下模態對話框的css樣式該如何顯示
.shade{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: gray;
{# opacity: 0.8;#}
z-index: 100;
}
.modal{
position: fixed;
left: 50%;
top: 50%;
width: 280px;
height: 170px;
margin-left: -140px;
margin-top: -85px;
z-index: 101;
background-color: cadetblue;
border-radius: 10px;
}
這里記住,兩個postition都是fix,其中z-index越大,則越在上面
彈出的頁面效果如下

重置按鈕就是用input標簽實現,type為reset,就會清空input輸入框的值
取消按鈕我們也綁定了click事件,把之前那2個去掉hide屬性的標簽的hide屬性在加回去,找到標簽用addclass方式對標簽加class屬性
function del_register_form() {
$(".del_register_form").bind("click",function () {
$("#register_form").addClass("hide");
$("#shade").addClass("hide");
})
}
我們重點看下注冊按鈕的如何實現的,因為我們用的模態對話框實現的注冊效果,如果用模態對話框的方式,則往后台提交數據我們一般使用ajax的方式向后台提交數據
我們為注冊的input的按鈕也綁定了click事件,下面我們看下這個函數
function bind_ajax_register() {
$("#ajax_register").bind("click",function () {
var new_user_name = $("#register_username").val();
var new_user_pwd = $("#register_userpwd").val();
$.ajax(
{
url:"/zhaoshebei/form_register/",
type:"post",
data:{
user_name:new_user_name,
user_pwd:new_user_pwd
},
success:function (data) {
data = JSON.parse(data);
var statues = data["status"];
if (statues == "failed"){
$("#error_register").html(data["error"])
}else {
window.location.href = "/zhaoshebei/index/?uname="+new_user_name;
}
}
}
)
})
}
這里了我們會和后台進行交互了,首先val()獲取用戶注冊的用戶名和密碼,放在data中,然后通過post的方式傳遞給url指定的路徑
這里我們實現的效果是注冊后直接跳轉到index頁面,在ajax中,實現跳轉到某個url使用方法windows.location.href = url路徑就會跳轉到指定的路徑上,這里有一個點需要主要,如果我們在ajax跳轉要傳遞一個變量的時候,要用下面的方式,+ 變量名

由於后台傳遞過來的是一個字段,且用json.dumps處理過,所以在ajax中如果想要拿到這個字典對象則需要使用JSON.parse處理,則就可以拿到后台傳遞過來的字典對象
success的意思,如果整個流程走通,就會執行的函數,而函數data的值就是后台通過HttpResponse傳遞過來的值
最后我們看下后端的函數是如何處理的
def form_register(request):
method = request.method.lower()
if method == "post":
new_user_name = request.POST.get("user_name",None)
new_user_pwd = request.POST.get("user_pwd",None)
ret_dict = {"status":True,"error":None}
if not(bool(new_user_name)) or not(bool(new_user_pwd)):
state_dict = {"status": "failed", "error": "用戶名或者密碼不能為空"}
return HttpResponse(json.dumps(state_dict))
else:
if models.user_table.objects.filter(user_name=new_user_name).exists():
ret_dict["status"] = "failed"
ret_dict["error"] = "當前用戶已經存在"
return HttpResponse(json.dumps(ret_dict))
else:
models.user_table.objects.create(
user_name = new_user_name,
user_pwd = new_user_pwd,
)
return HttpResponse(json.dumps(ret_dict))
else:
# return redirect("/zhaoshebei/login/")
pass
這里需要注意的就是一點,如果前台是ajax的方式,則后端給前端返回數據,則要通過HttpResponse的方式
首先通過request.Post.get方式獲取前端傳遞過來的數據,進行是否為空,是否已經存在的判斷,然后通過HttpResponse的方式給后端返回,如果上述的判斷均通過,則調用model的create的命令在數據庫中增加數據
下面我們看下登陸是如何實現的
我們同樣為id為login的input標簽綁定了一個事件,下面我們看下事件的函數
function bind_login_func() {
$("#login").bind("click",function () {
$(".error").html("");
$("#login_form").removeClass("hide");
$("#shade").removeClass("hide");
})
}
同樣也是使用removeclass方式把模態對話框的hide屬性移除掉

我們先看下取消按鈕
<div class="hide modal" id="login_form">
<form action="/zhaoshebei/login/" method="post">
<p><label for="login_username">用戶:</label><input type="text" placeholder="用戶名" name="user_name" id="login_username"></p>
<p><label for="login_userpwd">密碼:</label><input type="password" placeholder="密碼" name="user_pwd" id="login_userpwd"></p>
<p><span class="error"></span></p>
<input type="button" value="登陸" id="ajax_login">
<input type="button" value="取消" class="del_login_form">
</form>
</div>
取消按鈕同樣綁定了click事件,把模態對話框的hide屬性加回去
function del_login_form() {
$(".del_login_form").bind("click",function () {
$("#login_form").addClass("hide");
$("#shade").addClass("hide");
})
}
重點看下登陸按鈕,同樣綁定了click事件,通過ajax的方式把數據傳遞給后台,因為我們這里同樣適用模態對話框的方式,所以適用ajax的方式和后台進行交互
function bind_ajax_login() {
$("#ajax_login").bind("click",function () {
var user_name = $("#login_username").val();
var user_pwd = $("#login_userpwd").val();
{# $(".error").val()#}
$.ajax(
{
url:"/zhaoshebei/form_login/",
type:"post",
data:{
user_name:user_name,
user_pwd:user_pwd
},
success:function (data) {
data = JSON.parse(data);
var statues = data["status"];
if (statues == "failed"){
$(".error").html(data["error"])
}else {
window.location.href = "/zhaoshebei/index/?uname="+user_name;
}
}
}
)
})
}
和注冊的ajax的用法基本上一致
這里看下報錯的信息適用$(".error").html("錯誤信息")來在頁面顯示報錯
我們最后在登陸的后台的代碼
def form_login(request):
if request.method == "POST":
username = request.POST.get("user_name",None)
userpwd = request.POST.get("user_pwd",None)
state_dict = {"status": True, "error": None}
if not(bool(username)) or not(bool(userpwd)):
state_dict = {"status": "failed", "error": "用戶名或者密碼不能為空"}
return HttpResponse(json.dumps(state_dict))
else:
ret = models.user_table.objects.filter(user_name=username,user_pwd=userpwd).exists()
if ret:
request.session["username"] = username
request.session["userpwd"] = userpwd
state_dict = {"status": True, "error": None}
return HttpResponse(json.dumps(state_dict))
else:
state_dict["status"] = "failed"
state_dict["error"] = "用戶或者密碼錯誤"
return HttpResponse(json.dumps(state_dict))
這里需要注意,和注冊的函數有一點不同,這里如果登陸成功,我們要設置session

我們在訪問其他的頁面,不能每次都要求客戶登陸,所以要把認證信息放在session后,用戶的每次方法的request的請求都會有session信息,所有我們會把校驗session的放在裝飾器中,我們看下裝飾器函數
def outer(func):
def inner(request):
session_uname = request.session.get("username",None)
session_userpwd = request.session.get("userpwd",None)
if models.user_table.objects.filter(user_name=session_uname,user_pwd=session_userpwd).exists():
# print(session_userpwd,session_uname)
ret = func(request)
return ret
else:
return redirect("/zhaoshebei/login/")
return inner
第一個頁面講解完了,明天講解一下第二個頁面
二、所有設備頁面
由於我們的所有設備頁面, 正常設備的頁面,丟失設備的頁面,退庫設備的頁面基本都是一樣的,只有中間框的內容不一樣,所以我們先寫一個模板html,讓其他頁面都來繼承這個頁面即可
先看下基鏡像的html代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>資產管理</title>
<link rel="stylesheet" href="/static/cs/css1.css">
<style>
{% block css %}
{% endblock %}
</style>
</head>
<body>
<div id="menu_head">
<h2>設備管理</h2>
<div>
歡迎{{ username }}登陸|<a href="/zhaoshebei/logout/">注銷</a>
</div>
</div>
<div id="menu_left">
<div>
<a id="menu_all_device" href="/zhaoshebei/index/?uname={{ username }}">所有設備</a>
<a id="menu_exist" href="/zhaoshebei/exist_device/?uname={{ username }}">正常的設備</a>
<a id="menu_discard" href="/zhaoshebei/discard_device/?uname={{ username }}">退庫的設備</a>
<a id="menu_lost" href="/zhaoshebei/lost_device/?uname={{ username }}">丟失的設備</a>
</div>
</div>
<div id="menu_right">
{% block content %}
{% endblock %}
</div>
<script src="/static/jq/jquery-3.3.1.min.js"></script>
{% block jq %}
{% endblock %}
</body>
</html>
我們看到在母版中的html引入了一個css文件,我們為什么可以引入css文件,因為我們在settings設置靜態文件的路徑
STATICFILES_DIRS = (
os.path.join(BASE_DIR,"static"),
)
這個時候我們就可以把靜態文件放在static路徑下,童顏高可用創建子目錄

這樣我們就可以引入css文件了,引入css文件的方式如下
<link rel="stylesheet" href="/static/cs/css1.css">
我們來看下這個css文件是怎么寫的
*{
margin: 0px;
}
#menu_head{
width: 100%;
height: 48px;
background-color: darkgray;
color: black;
}
#menu_head div{
float: right;
font-size: 20px;
}
#menu_head h2{
padding-left: 500px;
display: inline;
}
#menu_left div{
position: absolute;
top: 48px;
width: 130px;
left: 0px;
bottom: 0px;
background-color: cornflowerblue;
/*min-height:1000px;*/
}
#menu_left a{
display: block;
padding-left: 10px;
padding-bottom: 10px;
border-left: 1px;
color: yellow;
font-size: 20px;
}
#menu_left a:hover{
background-color: green;
}
.active{
background-color: purple;
}
#menu_right{
position: absolute;
top: 48px;
left: 130px;
bottom: 0px;
background-color: white;
right: 0;
}
div a{
padding: 10px;
}
這里我們重點下這個css的代碼的意思
#menu_left a:hover{
background-color: green;
}
.active{
background-color: purple;
}
為左邊的a標簽設置了hover屬性,設置了這個屬性后,如果我們鼠標滑過a標簽,則會為a標簽賦予背景色為綠色的效果

另外外面還定義了一個.active的css屬性,意思就是如果選中的話,該a標簽會顯示這個css屬性,背景色為purple

我們只需要重寫block中的代碼就可以了
下面我們正式看下所有設備的頁面
{% extends "base.html" %}
{% block css %}
<style>
textarea{
overflow:scroll;
}
.active_page{
color: yellow;
font-size: larger;
background-color: black;
}
.shade{
position: fixed;
z-index: 100;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: gray;
}
.modal{
position: fixed;
z-index: 101;
width: 200px;
height: 150px;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -75px;
background-color: aquamarine;
}
.hide{
display: none;
}
</style>
{% endblock %}
{% block content %}
<input type="button" value="導出" class="import_botton">
<form>
<table border="1">
<caption><h2>所有的設備</h2></caption>
<thead>
<tr>
<td>所屬部門</td>
<td>資產編碼</td>
<td>資產名稱</td>
<td>資產狀態</td>
<td>設備SN碼</td>
<td>設備位置</td>
<td>設備備注</td>
<td>責任人</td>
<td>最后已更新時間</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{% for device in all_device_list %}
<tr>
<td>{{ device.device_partment }}</td>
<td id="{{ device.id }}">{{ device.device_id }}</td>
<td>{{ device.device_name }}</td>
<td>{{ device.device_status }}</td>
<td>{{ device.device_sn }}</td>
<td>{{ device.device_position }}</td>
<td><textarea name="device_remark" rows="3" cols="21">{{ device.device_remark }}</textarea></td>
<td>{{ device.device_user__user_name }}</td>
<td>{{ device.device_edit_time|date:"Y-m-d H:i:s" }}</td>
<td><a href="/zhaoshebei/edit_device/?device_did={{ device.id }}&uname={{ username }}">編輯</a>|<a href="/zhaoshebei/del_device/?device_did={{ device.id }}&uname={{ username }}">刪除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
<div>
{{ page_spilt_str|safe }}
</div>
<a style="margin-top: 50px" href="/zhaoshebei/add_device/?uname={{ username }}"><h2>添加新的設備</h2></a>
<div class="hide shade" id="import_shade"></div>
<div class="hide modal" id="import_modal">
<form>
<p>
<input type="checkbox" value="ok" name="import_list">:正常的設備
</p>
<p>
<input type="checkbox" value="lost" name="import_list">:丟失的設備
</p>
<p>
<input type="checkbox" value="discard" name="import_list">:退庫的設備
</p>
<input type="button" value="導出" id="confirm_import_data_new">
<input type="button" value="取消" class="delete_import">
</form>
</div>
{% endblock %}
{% block jq %}
<script src="/static/jq/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$("#menu_all_device").addClass("active");
import_data_form();
import_data_again();
delete_import();
});
function import_data_form() {
$(".import_botton").bind("click",function () {
$("#import_shade").removeClass("hide");
$("#import_modal").removeClass("hide");
})
}
function delete_import() {
$(".delete_import").bind("click",function () {
$("#import_shade").addClass("hide");
$("#import_modal").addClass("hide");
})
}
function import_data_again() {
$("#confirm_import_data_new").bind("click",function () {
var check_id = [];
$("input[type='checkbox']:checked").each(function(i){
check_id[i] =$(this).val();
});
check_id = JSON.stringify(check_id)
$.ajax({
url:"/zhaoshebei/import_func/?p={{ username }}",
type:"post",
data:{
"import_select_list":check_id,
},
success:function (data) {
{# alert(data)#}
window.location.href = "/zhaoshebei/big_file_download/?file=" + data
}
})
})
}
</script>
{% endblock %}
所有設備的頁面知識點很多,我們一一分解
1、首先是設備的列表是如何實現的,毫無疑問,我們使用table標簽來實現
<form>
<table border="1">
<caption><h2>所有的設備</h2></caption>
<thead>
<tr>
<td>所屬部門</td>
<td>資產編碼</td>
<td>資產名稱</td>
<td>資產狀態</td>
<td>設備SN碼</td>
<td>設備位置</td>
<td>設備備注</td>
<td>責任人</td>
<td>最后已更新時間</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{% for device in all_device_list %}
<tr>
<td>{{ device.device_partment }}</td>
<td id="{{ device.id }}">{{ device.device_id }}</td>
<td>{{ device.device_name }}</td>
<td>{{ device.device_status }}</td>
<td>{{ device.device_sn }}</td>
<td>{{ device.device_position }}</td>
<td><textarea name="device_remark" rows="3" cols="21">{{ device.device_remark }}</textarea></td>
<td>{{ device.device_user__user_name }}</td>
<td>{{ device.device_edit_time|date:"Y-m-d H:i:s" }}</td>
<td><a href="/zhaoshebei/edit_device/?device_did={{ device.id }}&uname={{ username }}">編輯</a>|<a href="/zhaoshebei/del_device/?device_did={{ device.id }}&uname={{ username }}">刪除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
這里我們梳理一下,我們首先使用了模板語言的循環,來接受后端傳遞來個設備列表信息

下面我們來看下后端是如何傳遞來的數據
@outer
def index(request):
method = request.method.lower()
if method == "get":
username = request.GET.get("uname")
obj = models.user_table.objects.get(user_name=username)
all_device_list = obj.device_table_set.all().values("id","device_partment","device_id","device_name","device_status","device_sn","device_position","device_remark","device_user__user_name","device_edit_time")
count = obj.device_table_set.all().count()
current_page = int(request.GET.get("p","1"))
base_url = request.path
page_obj =page_split.page_helper(count=count,current_page=current_page,per_page_num=6,base_url=base_url,uname=username)
all_device_list = obj.device_table_set.all()[page_obj.db_start():page_obj.db_end()].values("id","device_partment","device_id","device_name","device_status","device_sn","device_position","device_remark","device_user__user_name","device_edit_time")
page_spilt_str = page_obj.page_list()
return render(request,"index.html",locals())
else:
return redirect("/zhaoshebei/login/")
首先如果是get請求過來,我們要從數據庫中拿數據,首先在我們需要拿到這個用戶的id,然后從數據庫中獲取該用戶的設備信息
username = request.GET.get("uname")
后端去獲取用戶信息,則前端就一定要傳遞過來,我們看下前端是如何傳遞過來的,我們可以看到,是通過url路徑的方式,使用+傳遞過來的用戶的名稱

后端拿到用戶名稱后,因為我們的用戶名稱是唯一的,所以去數據庫中通過用戶id去拿到這個用戶的所有的信息
obj = models.user_table.objects.get(user_name=username)
all_device_list = obj.device_table_set.all().values("id","device_partment","device_id","device_name","device_status","device_sn","device_position","device_remark","device_user__user_name","device_edit_time")
因為我們拿到的用戶表中的信息,但是設備信息我們放在設備表中,因為用戶表和設備表是一對多的關系,所以在valus中我們可以雙下划線__去做跨表查詢,拿到這個用戶的設備信息
拿到數據后,因為我們前端需要分頁顯示,所以我們需要使用count方法獲取這個用戶的設備的數量,來進行分頁顯示

我們把分頁的代碼單獨寫在一個目錄中

下面我們看下分頁的代碼,分頁的代碼這里就講解了,可以自己看下
class page_helper():
def __init__(self,count,current_page,per_page_num,base_url,uname):
self.count = count
self.current_page = current_page
self.per_page_num = per_page_num
self.base_url = base_url
self.uname = uname
def page_count(self):
before, after = divmod(self.count, self.per_page_num)
if after > 0:
class_count = before + 1
else:
class_count = before
return class_count
def page_start(self):
if self.page_count() <= 11:
start_int = 1
end_int = self.page_count()
else:
if self.current_page <= 6:
start_int = 1
end_int = 11
elif self.current_page + 5 + 1 > self.page_count():
start_int = self.page_count() - 10
end_int = self.page_count() + 1
else:
start_int = self.current_page - 5
end_int = self.current_page + 5 + 1
return start_int
def page_end(self):
if self.page_count() <= 11:
start_int = 1
end_int = self.page_count()
else:
if self.current_page <= 6:
start_int = 1
end_int = 11
elif self.current_page + 5 + 1 > self.page_count():
start_int = self.page_count() - 10
end_int = self.page_count() + 1
else:
start_int = self.current_page - 5
end_int = self.current_page + 5 + 1
return end_int
def db_start(self):
return (self.current_page - 1) * self.per_page_num
def db_end(self):
return self.current_page * self.per_page_num
def page_list(self):
if self.current_page == 1:
before_page = """<a href="#">上一頁</a>"""
else:
before_page = """<a href="{url}?p={num}&uname={uname}">上一頁</a>""".format(url=self.base_url,num=self.current_page - 1,uname=self.uname)
page_list = []
page_list.append(before_page)
for i in range(self.page_start(),self.page_end() + 1):
if i == self.current_page:
s = """<a href="{url}?p={num}&uname={uname}" class="active_page">{num}</a>""".format(url=self.base_url,num=i,uname=self.uname)
else:
s = """<a href="{url}?p={num}&uname={uname}">{num}</a>""".format(url=self.base_url,num=i,uname=self.uname)
page_list.append(s)
if self.current_page == self.page_count():
after_page = """<a href="#">下一頁</a>"""
else:
after_page = """<a href="{url}?p={num}&uname={uname}">下一頁</a>""".format(url=self.base_url,num=self.current_page + 1,uname=self.uname)
page_list.append(after_page)
page_str = "".join(page_list)
return page_str
我們在views中導入分頁的代碼就可以了,因為第一次用戶登陸,他沒有傳遞頁數,所以我們需要給頁數一個默認值,這里默認給一個1就可以了
current_page = int(request.GET.get("p","1"))
base_url = request.path
page_obj =page_split.page_helper(count=count,current_page=current_page,per_page_num=6,base_url=base_url,uname=username)
all_device_list = obj.device_table_set.all()[page_obj.db_start():page_obj.db_end()].values("id","device_partment","device_id","device_name","device_status","device_sn","device_position","device_remark","device_user__user_name","device_edit_time")
page_spilt_str = page_obj.page_list()
然后通過render返回給前端
return render(request,"index.html",locals())
我們看到的所有設備的頁面還有編輯和刪除2個按鈕,下面我們看下編輯和刪除
先看編輯,由於用戶的名稱的對我們非常重要,所以我們在url務必要把用戶信息傳遞給后端,方便后端處理


<td><a href="/zhaoshebei/edit_device/?device_did={{ device.id }}&uname={{ username }}">編輯</a>|<a href="/zhaoshebei/del_device/?device_did={{ device.id }}&uname={{ username }}">刪除</a></td>
我們看下編輯的后端是如何處理的
@outer
def edit_device(request):
from django.utils.safestring import mark_safe
method = request.method.lower()
if method == "get":
username = request.GET.get("uname")
device_did = request.GET.get("device_did")
edit_obj = models.device_table.objects.get(id=device_did)
device_partment = edit_obj.device_partment
device_id = edit_obj.device_id
device_name = edit_obj.device_name
device_status = edit_obj.device_status
device_sn = edit_obj.device_sn
device_postion = edit_obj.device_position
device_remark = edit_obj.device_remark
device_user = edit_obj.device_user
if device_status == "ok":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" selected="selected"> 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
elif device_status == "lost":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost" selected="selected"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
elif device_status == "discard":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" selected="selected"> 退庫 </option></select>"""
else:
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
return render(request,"edit_device.html",locals())
else:
device_edit_info_dict = request.POST
username = device_edit_info_dict["username"]
device_partment = request.POST.get("device_partment")
if not device_edit_info_dict["device_partment"]:
device_partment_error = "部門名稱不允許為空"
return render(request, "edit_device.html", locals())
else:
# device_id = request.POST.get("device_id")
if not device_edit_info_dict["device_id"]:
device_id_error = "該設備編碼不允許為空"
return render(request, "edit_device.html", locals())
else:
if not device_edit_info_dict["device_status"]:
device_status_error = "設備狀態不允許為空"
return render(request, "edit_device.html", locals())
else:
try:
models.device_table.objects.filter(id=int(device_edit_info_dict["id"])).update(
device_partment = request.POST.get("device_partment"),
device_id = request.POST.get("device_id"),
device_name = request.POST.get("device_name"),
device_status = request.POST.get("device_status"),
device_sn = request.POST.get("device_sn"),
device_position = request.POST.get("device_position"),
device_remark = request.POST.get("device_remark")
)
models.device_table.objects.filter(id=int(device_edit_info_dict["id"]))[0].save()
except Exception as e:
print(e,"-----------------------------------")
else:
return redirect(("/zhaoshebei/index/?uname={name}".format(name=username)))
編輯的后端代碼需要處理get請求,同時也需要處理post請求,我們先看下get請求是如何處理的,拿到用戶通過url方式傳遞過來的用戶信息,然后從數據庫中獲取數據,然后render的方式渲染給前端
if method == "get":
username = request.GET.get("uname")
device_did = request.GET.get("device_did")
edit_obj = models.device_table.objects.get(id=device_did)
device_partment = edit_obj.device_partment
device_id = edit_obj.device_id
device_name = edit_obj.device_name
device_status = edit_obj.device_status
device_sn = edit_obj.device_sn
device_postion = edit_obj.device_position
device_remark = edit_obj.device_remark
device_user = edit_obj.device_user
if device_status == "ok":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" selected="selected"> 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
elif device_status == "lost":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost" selected="selected"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
elif device_status == "discard":
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" selected="selected"> 退庫 </option></select>"""
else:
device_status_str = """<select name = "device_status" size = "3"><option value = "ok" > 正常 </option><option value = "lost"> 丟失 </option><option value = "discard" > 退庫 </option></select>"""
return render(request,"edit_device.html",locals())
前端的代碼
{% extends "base.html" %}
{% block css %}
<style>
textarea{
overflow:scroll;
}
span{
color: red;
}
</style>
{% endblock %}
{% block content %}
<h2>編輯設備信息</h2>
<form action="/zhaoshebei/edit_device/" method="post">
<input type="text" value="{{ username }}" name="username" style="display:none;">
<input type="text" value="{{ device_did }}" name="id" style="display: none">
<p><label for="device_partment">所屬部門:</label><br><input type="text" placeholder="所屬部門" name="device_partment" id="device_partment" value="{{ device_partment }}"></p>
<span>{{ device_partment_error }}</span><br>
<p><label for="device_id">資產編碼:</label><br><input type="text" placeholder="資產編碼" name="device_id" id="device_id" value="{{ device_id }}"></p>
<span>{{ device_id_error }}</span><br>
<p><label for="device_name">資產名稱:</label><br><input type="text" placeholder="資產名稱,可不填" name="device_name" id="device_name" value="{{ device_name }}"></p>
<p><label for="device_sn">資產SN碼:</label><br><input type="text" placeholder="資產SN碼,可不填" name="device_sn" id="device_sn" value="{{ device_sn }}"></p>
<p><label for="device_position">資產位置:</label><br><input type="text" placeholder="資產位置,可不填" name="device_postion" id="device_postion" value="{{ device_postion }}"></p>
<p><label for="device_user__user_name">責任人:</label><br><input type="text" disabled="disabled" placeholder="責任人" name="device_user" id="device_user" value="{{ device_user }}"></p>
設備描述:<br><textarea name="device_remark" rows="3" cols="21" placeholder="設備描述,可不填">{{ device_remark }}</textarea><br>
設備狀態:<br>
{{device_status_str|safe}}
<br>
<span>{{ device_status_error }}</span><br>
<input type="submit" value="提交">
<a href="/zhaoshebei/index/?uname={{ username }}">取消</a>
</form>
{% endblock %}
{% block jq %}
<script src="/static/jq/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$("#menu_all_device").addClass("active")
})
</script>
{% endblock %}
然后我們看下后端代碼的post請求是處理
device_edit_info_dict = request.POST
username = device_edit_info_dict["username"]
device_partment = request.POST.get("device_partment")
if not device_edit_info_dict["device_partment"]:
device_partment_error = "部門名稱不允許為空"
return render(request, "edit_device.html", locals())
else:
# device_id = request.POST.get("device_id")
if not device_edit_info_dict["device_id"]:
device_id_error = "該設備編碼不允許為空"
return render(request, "edit_device.html", locals())
else:
if not device_edit_info_dict["device_status"]:
device_status_error = "設備狀態不允許為空"
return render(request, "edit_device.html", locals())
else:
try:
models.device_table.objects.filter(id=int(device_edit_info_dict["id"])).update(
device_partment = request.POST.get("device_partment"),
device_id = request.POST.get("device_id"),
device_name = request.POST.get("device_name"),
device_status = request.POST.get("device_status"),
device_sn = request.POST.get("device_sn"),
device_position = request.POST.get("device_position"),
device_remark = request.POST.get("device_remark")
)
models.device_table.objects.filter(id=int(device_edit_info_dict["id"]))[0].save()
except Exception as e:
print(e,"-----------------------------------")
else:
return redirect(("/zhaoshebei/index/?uname={name}".format(name=username)))
拿到用戶信息后,先做基本的判斷,然后通過update方法更新數據庫中的信息就可以了
這里我們需要補充一個點,我們看下我們的數據庫的設計

這里我在實際測試中,發現未更新,最終發現調用一下save方法,這個時間就會更新了

下面我們看下刪除


先看取消按鈕是怎么實現,就是a標簽
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<h2>刪除設備</h2>
<form action="/zhaoshebei/del_device/" method="post">
<input type="text" value="{{ username }}" name="username" style="display:none;">
<input type="text" value="{{ did }}" name="id" style="display: none">
<input type="text" value="{{ device_id }}" style="display: block">
<input type="submit" value="確定刪除">|<a href="/zhaoshebei/index/?uname={{ username }}">取消</a>
</form>
{% endblock %}
{% block jq %}
<script src="/static/jq/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$("#menu_all_device").addClass("active")
})
</script>
{% endblock %}

下面看下確定刪除的按鈕

在看下后端的代碼是如何實現的,同樣這個函數也需要用裝飾器裝飾
@outer
def del_device(request):
method = request.method.lower()
if method == "get":
username = request.GET.get("uname")
did = request.GET.get("device_did")
# print(id)
device_id = models.device_table.objects.get(id=did).device_id
return render(request,"delete_device.html",locals())
else:
username = request.POST.get("username")
did = request.POST.get("id")
models.device_table.objects.get(id=did).delete()
return redirect("/zhaoshebei/index/?uname={name}".format(name=username))
如果是get請求,則拿到用戶信息和設備id,通過render方式渲染給前端,如果post請求,則調用delete方法刪除對應的信息,然后通過redirect重定向到index頁面,這里也需要主要,重定向的url也務必要傳遞用戶信息,丟失了用戶名稱,頁面就不知道怎么渲染了

最后我們添加的設備是如何實現的


先看下html代碼
{% extends "base.html" %}
{% block css %}
<style>
textarea{
overflow:scroll;
}
span{
color: red;
}
</style>
{% endblock %}
{% block content %}
<form method="post" action="/zhaoshebei/add_device/?uname={{ username }}">
<p><label for="device_partment">所屬部門:</label><br><input type="text" placeholder="所屬部門" name="device_partment" id="device_partment"></p>
<span>{{ device_partment_error }}</span><br>
<p><label for="device_id">資產編碼:</label><br><input type="text" placeholder="資產編碼" name="device_id" id="device_id"></p>
<span>{{ device_id_error }}</span><br>
<p><label for="device_name">設備名稱:</label><br><input type="text" placeholder="設備名稱,可不填" name="device_name" id="device_name"></p>
<p><label for="device_sn">設備sn:</label><br><input type="text" placeholder="設備sn,可不填" name="device_sn" id="device_sn"></p>
<p><label for="device_position">設備位置:</label><br><input type="text" placeholder="設備位置,可不填" name="device_position" id="device_position"></p>
設備描述:<br><textarea name="device_remark" rows="3" cols="21" placeholder="設備描述,可不填"></textarea><br>
設備狀態:<br>
<select name="device_status" size="3">
<option value="ok">正常</option>
<option value="lost">丟失</option>
<option value="discard">退庫</option>
</select>
<span>{{ device_status_error }}</span><br>
<br>
<input type="reset" value="重置">
<input type="submit" value="提交">
<a href="/zhaoshebei/index/?uname={{ username }}">取消</a>
</form>
{% endblock %}
{% block jq %}
<script src="/static/jq/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$("#menu_all_device").addClass("active")
})
</script>
{% endblock %}
先看取消和重置按鈕
取消按鈕

重置按鈕

下面下添加的頁面,使用form表單的方式和后端進行交互,用到input標簽和slect標簽
<form method="post" action="/zhaoshebei/add_device/?uname={{ username }}">
<p><label for="device_partment">所屬部門:</label><br><input type="text" placeholder="所屬部門" name="device_partment" id="device_partment"></p>
<span>{{ device_partment_error }}</span><br>
<p><label for="device_id">資產編碼:</label><br><input type="text" placeholder="資產編碼" name="device_id" id="device_id"></p>
<span>{{ device_id_error }}</span><br>
<p><label for="device_name">設備名稱:</label><br><input type="text" placeholder="設備名稱,可不填" name="device_name" id="device_name"></p>
<p><label for="device_sn">設備sn:</label><br><input type="text" placeholder="設備sn,可不填" name="device_sn" id="device_sn"></p>
<p><label for="device_position">設備位置:</label><br><input type="text" placeholder="設備位置,可不填" name="device_position" id="device_position"></p>
設備描述:<br><textarea name="device_remark" rows="3" cols="21" placeholder="設備描述,可不填"></textarea><br>
設備狀態:<br>
<select name="device_status" size="3">
<option value="ok">正常</option>
<option value="lost">丟失</option>
<option value="discard">退庫</option>
</select>
這里我們復習一下select標簽

頁面的效果

其他input標簽就是正常的用戶,但是要務必要name屬性,這樣后端才能正常獲取數據

下面我們看下后端代碼
@outer
def add_device(request):
method = request.method.lower()
if method == "get":
device_id_error = ""
username = request.GET.get("uname")
return render(request,"add_device.html",locals())
else:
username = request.GET.get("uname")
device_partment = request.POST.get("device_partment")
if not device_partment:
device_partment_error = "部門名稱不允許為空"
return render(request, "add_device.html", locals())
else:
device_id = request.POST.get("device_id")
if not device_id:
device_id_error = "資產編碼不允許為空"
return render(request, "add_device.html", locals())
else:
if models.device_table.objects.filter(device_id=device_id).exists():
device_id_error = "資產編碼已經存在"
return render(request,"add_device.html",locals())
else:
device_status = request.POST.get("device_status")
if not device_status:
device_status_error = "資產狀態不允許為空"
return render(request, "add_device.html", locals())
else:
obj = models.user_table.objects.get(user_name=username)
device_partment = request.POST.get("device_partment")
device_name = request.POST.get("device_name",None)
device_id = request.POST.get("device_id")
device_status = request.POST.get("device_status")
device_sn = request.POST.get("device_sn",None)
device_position = request.POST.get("device_position")
device_remark = request.POST.get("device_remark",None)
models.device_table.objects.create(
device_partment = device_partment,
device_id = device_id,
device_name = device_name,
device_status=device_status,
device_sn = device_sn,
device_position=device_position,
device_remark = device_remark,
device_user = obj
)
return redirect("/zhaoshebei/index/?uname={name}".format(name=username))

判斷通過,則調用post.get方法去獲取前端傳遞過來的值,然后調用create方法去數據庫中增加數據

下面我們下導出的實現,這個是浪費了我不少時間


我們看為這個input標簽綁定了ajax事件,導出我們是用ajax+模態對話框實現的,所有需要模態對話框,這里是把模態對話顯示和隱藏
function import_data_form() {
$(".import_botton").bind("click",function () {
$("#import_shade").removeClass("hide");
$("#import_modal").removeClass("hide");
})
}
function delete_import() {
$(".delete_import").bind("click",function () {
$("#import_shade").addClass("hide");
$("#import_modal").addClass("hide");
})
}

我們為這個導出按鈕再次綁定了一個ajax事件
function import_data_again() {
$("#confirm_import_data_new").bind("click",function () {
var check_id = [];
$("input[type='checkbox']:checked").each(function(i){
check_id[i] =$(this).val();
});
check_id = JSON.stringify(check_id)
$.ajax({
url:"/zhaoshebei/import_func/?p={{ username }}",
type:"post",
data:{
"import_select_list":check_id,
},
success:function (data) {
{# alert(data)#}
window.location.href = "/zhaoshebei/big_file_download/?file=" + data
}
})
})
}


后台拿到數據后,把數據從數據庫讀取出來,然后寫到excel中,然后把文件對象發給前端
@outer
def import_func(request):
method = request.method.lower()
if method == "post":
# print(request.POST)
username = request.GET.get("p")
import_select_list = request.POST.get("import_select_list")
s = ""
import_select_list = json.loads(import_select_list)
l = len(import_select_list)
# print(import_select_list)
if l == 1:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username) & Q(device_status="{arg}".format(arg=import_select_list[0])))
elif l == 2:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username) & (Q(device_status="{arg1}".format(arg1=import_select_list[0])) | Q(device_status="{arg2}".format(arg2=import_select_list[1]))))
elif l == 3:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username))
else:
list_obj = models.device_table.objects.all(Q(device_user__user_name=username))
import urllib
import_time = time.strftime("%Y_%m_%d_%H_%M_%S",time.localtime())
filename = import_time + ".xlsx"
file = os.path.join("static","file",filename)
workbook = xlsxwriter.Workbook(file)
worksheet = workbook.add_worksheet(name="設備管理")
row = 0
top = workbook.add_format(
{'border': 1, 'align': 'center', 'bg_color': 'cccccc', 'font_size': 13, 'bold': True}) # 創建標題名稱及背景顏色
top_list = [
'所屬部門',
'資產編碼',
'資產名稱',
'設備狀態',
'資產SN碼',
'資產位置',
'資產備注',
'責任人'
] # 內容
c = 0
for i in top_list:
worksheet.write(row,c,i,top)
c += 1
start_row = 1
for data in list_obj.values_list("device_partment","device_id","device_name","device_status","device_sn","device_position","device_remark","device_user__user_name"):
data = list(data)
if data[3] == "lost":
data[3] = "丟失"
# print(type(data), type(data[3]))
elif data[3] == "ok":
# print(type(data), type(data[3]))
data[3] = "正常"
else:
# print(type(data),type(data[3]))
data[3] = "退庫"
worksheet.write(start_row,0,data[0])
worksheet.write(start_row,1,data[1])
worksheet.write(start_row,2,data[2])
worksheet.write(start_row,3,data[3])
worksheet.write(start_row,4,data[4])
worksheet.write(start_row,5,data[5])
worksheet.write(start_row,6,data[6])
worksheet.write(start_row,7,data[7])
start_row += 1
workbook.close()
# response = big_file_download(request)
return HttpResponse(file)
前端拿到文件對象后,訪問下載的函數,實現下載

最后在看下下載的函數
def big_file_download(request):
# do something...
def file_iterator(file_name, chunk_size=512):
with open(file_name,"rb") as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
the_file_name = request.GET.get("file")
response = StreamingHttpResponse(file_iterator(the_file_name))
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="{0}"'.format(the_file_name)
return response
這里我們在后端拿數據的時候用到model的Q查詢
if l == 1:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username) & Q(device_status="{arg}".format(arg=import_select_list[0])))
elif l == 2:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username) & (Q(device_status="{arg1}".format(arg1=import_select_list[0])) | Q(device_status="{arg2}".format(arg2=import_select_list[1]))))
elif l == 3:
list_obj = models.device_table.objects.filter(Q(device_user__user_name=username))
else:
list_obj = models.device_table.objects.all(Q(device_user__user_name=username))
這里要注意括號的運用,
注銷函數的后台實現

