- github地址 :
https://github.com/Dalao-Li/RegisterSystem-Django.git
- CSDN下载 : 源代码
- 相关博客 : 体温登记系统-Flask版
配置
- 宿主机 : Windows10 2004
- 部署环境 : CentOS7
- IDE : Pycharm
涉及技术
- CSS : Bootstrap
- JS : JQuery
- 弹窗控件 : SweetAlert2
- Web框架 : Django
- 数据库 : Sqlite3
初始化
- 建立Django项目demo
建立一个应用app
python manage.py startapp app
项目结构
- 修改settings.py文件
在INSTALLED_APPS中添加刚创建的应用
在MIDDLEWARE中注释django.middleware.csrf.CsrfViewMiddleware
修改语言与时区
数据库设计
- 数据库
本项目中采用默认的sqlite3数据库
- 表设计
名称 | 类型 | 说明 |
---|---|---|
num | CharField | 学号 |
name | CharField | 姓名 |
temperate | FloatField | 温度 |
date | DateTimeField | 上传日期与时间 |
编辑app/models.py文件
from django.db import models
# Create your models here.
class Reocrd(models.Model):
num = models.CharField(
verbose_name='学号',
help_text='请输入学号',
max_length=8
)
name = models.CharField(
verbose_name='姓名',
help_text='请输入姓名',
max_length=5
)
temperature = models.FloatField(
verbose_name='体温',
help_text='请输入体温',
)
date = models.DateTimeField(
verbose_name='日期',
help_text='请选择日期与时间',
)
def __str__(self):
return self.num
终端执行,为改动创建迁移记录
python manage.py makemigrations
将操作同步到数据库
python manage.py migrate
- 创建管理员用户
python manage.py createsuperuser
输入用户名和密码,邮箱地址可选
模板文件
在app目录下新建templates文件夹
编辑settings.py文件,找到TEMPLATES,将新增模板的路径添加至DIRS项中:
在app/templates下新建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>体温登记系统</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'css/sweetalert.css' %}">
<link rel="stylesheet" href="{% static 'css/bootstrap-table.min.css' %}">
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/popper.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/sweetalert-dev.js' %}"></script>
<script src="{% static 'js/bootstrap-table.min.js' %}"></script>
<script src="{% static 'js/bootstrap-table-zh-CN.min.js' %}"></script>
<script src="{% static 'js/api.js' %}"></script>
<style>
.danger {
color: red;
font-weight: bold;
}
.safe {
color: green;
font-weight: bold;
}
</style>
</head>
<body>
<div style="text-align: center;">
<h2>体温登记</h2>
</div>
<table class="table table-hover">
<form id="recordForm">
<td>
<div class="input-group">
<label for="num"></label>
<input type="text" class="form-control" id="num" name="num" placeholder="请输入学号" minlength="8"
maxlength="8">
</div>
</td>
<td>
<div class="input-group">
<label for="name"></label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名" required >
</div>
</td>
<td>
<div class="input-group">
<label for="tem"></label>
<input type="number" class="form-control" id="tem" name="tem" placeholder="请输入体温" min="35" max="43"
step="0.1" required>
</div>
</td>
<td>
<div class="input-group">
<label for="date"></label>
<input type="datetime-local" class="form-control" id="date" name="date" placeholder="请选择日期" required>
</div>
</td>
<td>
<button type="submit" class="btn btn-primary" onclick=addRecord()>提交</button>
</td>
</form>
</table>
<table class="table table-hover" id="recordTable">
<thead>
<tr>
<th>序号</th>
<th>学号</th>
<th>姓名</th>
<th>体温</th>
<th>提交日期与时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for i in record %}
<tr>
<td>{{ i.id }}</td>
<td>{{ i.num }}</td>
<td>{{ i.name }}</td>
{% if i.temperature > 37.5 %}
<td class="danger">
{{ i.temperature }}
</td>
{% else %}
<td class="safe">
{{ i.temperature }}
</td>
{% endif %}
<td>{{ i.date }}</td>
<td>
<button type="button" class="btn btn-danger" οnclick=delRecord("{{ i.num }}")>删除</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$('#recordTable').bootstrapTable({
//是否显示分页条
pagination: true,
//首页页码
pageNumber: 1,
//一页显示的行数
pageSize: 5,
//是否开启分页条无限循环,最后一页时点击下一页是否转到第一页
paginationLoop: false,
//选择每页显示多少行,数据过少时可能会没有效果
pageList: [5, 10, 20],
//启用关键字搜索框
search: true
})
</script>
</body>
</html>
静态文件
app目录下新建static目录,存放静态文件
app/static/js目录下新建 api.js:
function sendAjax(param, url, callback) {
$.ajax({
async: false,
ache: false,
type: 'POST',
url: url,
//JSON对象转化JSON字符串
data: JSON.stringify(param),
//服务器返回的数据类型
dataType: "json",
//清除浏览器缓存
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (data) {
callback(data.result)
},
error: function (data) {
//错误处理
}
})
}
function addRecord() {
var data = {
'num': $('#num').val(),
'name': $('#name').val(),
'tem': $('#tem').val(),
'date': $('#date').val()
}
//判断非空
for(var k in data){
if(data[k] === ""){
return
}
}
sendAjax(data, '/app/add/', addCallback)
}
function addCallback(value) {
if (value === 1) {
swal({
title: "提交成功",
text: "",
type: "success",
timer: 2000
}, function () {
location.reload()
})
}
if (value === 0) {
swal("上交失败", "请重试", "error")
}
if (value === -1) {
swal({
title: "该学生体温已提交",
text: "请勿重复提交",
type: "warning"
}, function () {
$('#recordForm')[0].reset()
})
}
}
function delRecord(id) {
swal({
title: "您确定要删除该记录吗",
text: "删除后将无法恢复,请谨慎操作!",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "确认",
cancelButtonText: "取消",
closeOnConfirm: false,
closeOnCancel: false
},
function (isConfirm) {
if (isConfirm) {
var data = {'num': id}
sendAjax(data, '/app/del/', delCallback)
} else {
swal({
title: "已取消",
text: "您取消了删除操作!",
type: "warning"
})
}
}
)
}
function delCallback(value) {
if (value === 1) {
swal({
title: "删除成功",
text: "",
type: "success",
timer: 2000
}, function () {
location.reload()
})
return
}
if (value === -1) {
swal("删除失败", "请重试", "error")
}
}
项目最终结构
完整代码请访问博主的Github
视图函数
编辑app/views.py文件:
import json
from django.shortcuts import render, HttpResponse
from app.models import Reocrd
# Create your views here.
# 显示主页面
def index(request):
record = [i for i in Reocrd.objects.all()]
return render(request, 'index.html', {'record': record})
def add_record(request):
data = json.loads(request.body)
num, name, tem, date = data.values()
# 查询是否已经提交
if Reocrd.objects.filter(num=num).exists():
return HttpResponse(json.dumps({'result': -1}))
Reocrd.objects.create(num=num, name=name, temperature=tem, date=date)
return HttpResponse(json.dumps({'result': 1}))
def del_record(request):
data = json.loads(request.body)
num = list(data.values())[0]
Reocrd.objects.filter(num=num).delete()
if Reocrd.objects.filter(num=num).exists():
return HttpResponse(json.dumps({'result': -1}))
return HttpResponse(json.dumps({'result': 1}))
绑定路由
在app目录下新建urls.py文件:
from django.urls import path
from app import views
urlpatterns = [
# 将函数绑定至对应路由
path('', views.index),
path('add/', views.add_record),
path('del/', views.del_record)
]
编辑主目录下的urls.py文件:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
# 注册应用app的路由
path('app/',include('app.urls'))
]
运行项目,访问http://127.0.0.1/app/,查看
部署
本项目采用Docker + Gunicorn方式进行部署
部署后可能会出现无法访问静态文件的情况,因此编辑主目录下urls.py文件,新增:
from django.contrib import admin
from django.urls import path,include
# 新增
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
path('admin/', admin.site.urls),
# 注册应用app的路由
path('app/',include('app.urls')),
]
# 新增
urlpatterns += staticfiles_urlpatterns()
主目录下新建gunicorn_config.py文件:
# 定义同时开启的处理请求的进程数量,根据网站流量适当调整
workers = 5
# 采用gevent库,支持异步处理请求,提高吞吐量
worker_class = "gevent"
# 这里8000可以随便调整
bind = "0.0.0.0:8000"
# 超时
timeout = 30
生成项目依赖文件
pip freeze > requirements.txt
asgiref==3.2.10
cffi==1.14.1
Django==3.0.8
gevent==20.6.2
greenlet==0.4.16
gunicorn==20.0.4
pycparser==2.20
pytz==2020.1
sqlparse==0.3.1
zope.event==4.4
zope.interface==5.1.0
编写Dockerfile
#所采用的基础镜像
FROM python:3.7
# 为镜像添加标签
LABEL version="v1" description="Docker deploy Django" by="Dalao"
#程序的运行目录
WORKDIR /usr/django
#导入库依赖文件
COPY requirements.txt ./
#安装库
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
# 复制项目文件
COPY . .
# 容器启动时执行指令,每个Dockerfile只能有一条CMD命令
CMD ["gunicorn", "demo.wsgi", "-c", "gunicorn_config.py"]
将文件夹上传至服务器
进入demo目录
docker build -t mydemo .
运行容器,查看结果
docker run -itd -p 80:8000 mydemo