需求
安装Django mysqlclient
pip install Django -i https://pypi.douban.com/simple
pip install mysqlclient -i https://pypi.douban.com/simple
django-admin startproject temperature
cd temperature
python manage.py startapp tempapp
客户端
结构如下,需要新建templates文件夹,以及四个html文件
settings.py
"""
Django settings for temperature project.
Generated by 'django-admin startproject' using Django 2.2.6.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '_@-n@t+n32l)9m_-j+n5&la=9zbsgn4%wb$5c*kan6_zeftbb1'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tempapp'#需要把建立的app名字放在这
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'temperature.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'temperature.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
#需要修改数据库相关参数,我是用navicat新建了一个数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '温度',
'USER':'root',
'PASSWORD':'root123',
'HOST':'127.0.0.1',
'PORT':'3306',
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
#这里可以同步SOCKET接收数据时间和ORM存入数据库的时间
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
urls.py
"""temperature URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path
from tempapp import views
app_name ='tempapp'
urlpatterns = [
path('', views.index, name='index'),
path('select/', views.select,name='select'),
path('show/',views.show,name='show'),
path('newest/',views.newest,name='newest'),
]
models.py
from django.db import models
# 如果要将普通类映射为ORM模型,那么必须将父类设置为models.Model或它的子类
class temp(models.Model):
#1 id 自增长 int
id = models.AutoField(primary_key=True)
#2 位置
position = models.FloatField(default=0,null=False)
#3 温度
temperature = models.FloatField(default=0,null=False)
#4 时间
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
#<Book:(name,author,price)>
return "<temp:({id},{position},{temperature},{date_added})>".format(id=self.id,position=self.position,
temperature=self.temperature,date_added=self.date_added)
views.py
from django.shortcuts import render
from django.db import connection
from .models import temp
from django.shortcuts import render, HttpResponse, redirect, reverse
def get_cursor():
return connection.cursor()
def index(request):
return render(request,'index.html')
def show(request):
cursor = get_cursor()
cursor.execute("select id,position,date_added,temperature from tempapp_temp")
data_temps = cursor.fetchall() # 数据库所有数据
length = len(data_temps)
context ={
'data' : data_temps,
'length' : length}
return render(request, 'show.html',context)
def newest(request):
cursor = get_cursor()
cursor.execute("select id,position,date_added,temperature from tempapp_temp")
data_temps = cursor.fetchall() # 数据库所有数据
length = len(data_temps)
data_temps = data_temps[length-1]
context ={
'data' : data_temps,
'length' : length}
return render(request, 'newest.html',context)
# 查询
def select(request):
if request.method == "POST":
id = request.POST.get('id')
position = request.POST.get('position')
temperature = request.POST.get('temperature')
date_added = request.POST.get('date_added')
if id:
temp_data = temp.objects.filter(id=id).first()
if position:
temp_data = temp.objects.filter(position=position).all()
if temperature:
temp_data = temp.objects.filter(temperature=temperature).all()
if date_added:
temp_data = temp.objects.filter(date_added=date_added).first()
if temp_data == None:
#NoneType
return HttpResponse("错误")
else:
temp_datas = []
print(temp_data)
try:
length = len(temp_data)
for temp1 in temp_data:
id = temp1.id
position = temp1.position
temperature = temp1.temperature
date_added = temp1.date_added
datas = [id,position,temperature,date_added]
temp_datas.append(datas)
print(temp_datas)
context = {
'data': temp_datas,
'length': length,
'msg': True,
}
except TypeError:
length=1
id = temp_data.id
position = temp_data.position
temperature = temp_data.temperature
date_added = temp_data.date_added
datas = [id, position, temperature, date_added]
temp_datas.append(datas)
context = {
'data': temp_datas,
'length': length,
'msg': True,
}
return render(request, 'select.html', context)
else:
context = {
'msg' : False,
}
return render(request, 'select.html', context)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!--<meta charset="UTF-8" http-equiv="refresh" content="1" >-->
<meta charset="UTF-8">
<title>服务器端</title>
<script type="text/javascript">
function show(){
window.open("{% url 'show' %}",'newwindow','height=400,width=1200');}
</script>
<script type="text/javascript">
function select(){
window.open("{% url 'select' %}",'newwindow','height=400,width=1200');}
</script>
<script type="text/javascript">
function newest(){
window.open("{% url 'newest' %}",'newwindow','height=400,width=1200');}
</script>
<style type="text/css">
body{
height:100%;
width:100%;
overflow: hidden;
}
</style>
<style>
.box1{
padding: 10px 10px;
width:100%;
height:200px;
border:5px solid #F0F0F0;
text-align:center;
background-color:rgba(0,0,0,0.3);
}
div{
text-align:center;
}
p{
font-size:200%;
color:black;
font-weight:bold
}
h1{
font-size:500%;
color:#787878;
}
.button {
background-color: #404040; /* Blue */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 20px;
border-radius: 8px;
border: 5px solid white;
}
hr{height:5px;border:none;border-top:5px ridge black;width:80%}
</style>
</head>
<body >
<br>
<h1 align="center" >欢迎来到温度管理系统客户端</h1><br>
<div align="center" class="box1" >
<p> 请选择功能 </p>
<button type="button" class="button" onclick="show()">展示所有数据</button>
<button type="button" class="button" onclick="select()">检索数据</button>
<button type="button" class="button" onclick="newest()">展示最新数据</button>
</div>
</body>
</html>
newest.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最新数据</title>
</head>
<body>
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
<tr>
{% for j in data %}
<td align="center" id="lastdata" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
</table>
</body>
</html>
select.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" >
<title>检索界面</title>
</head>
<style type="text/css">
body{
height:100%;
width:100%;
overflow: hidden;
background-color: rgba(0,0,0,0.1);
}
h1{
font-size:400%;
color:black;
}
h2{
font-size:200%;
color:black;
}
h3{
font-size:100%;
color:red;
}
input[type=text], select {
width: 50%;
padding: 20px 20px;
margin: 8px 0;
<!--display: inline-block;-->
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 10%;
background-color: #4CAF50;
color: white;
padding: 20px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[value="查询"] {
font-size:80%;
}
input[type=submit]:hover {
background-color: #45a049;
}
.div{float:middle;}
form{
font-size:150%;
}
}
</style>
<body style="overflow:auto;">
<h1 align="center">检索界面</h1>
<div class="div">
{% if not msg %}
<h2 align="center">根据ID来查询温度</h2>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form1' action="/select/" align="center" >
{% csrf_token %}
ID:<input type="text" name="id" placeholder={{ id }}>
<input class="bc" type="submit" value="查询" align="center">
</form>
<br>
<hr>
<br>
<h2 align="center">根据位置来查询温度</h2>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form2' action="/select/" align="center">
{% csrf_token %}
位置:<input type="text" name="position" placeholder={{ position }}>
<input class="bc" type="submit" value="查询">
</form>
<br>
<hr>
<br>
<h2 align="center">根据时间来查询温度 格式如下</h2>
<h3 align="center" >2019-11-04 02:10:24</h3>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form3' action="/select/" align="center">
{% csrf_token %}
时间:<input type="text" name="date_added" placeholder={{ date_added }}>
<input class="bc" type="submit" value="查询" >
</form>
{% else %}
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
{% for k in data %}
<tr>
{% for j in k %}
<td align="center" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
{% endfor %}
</table>
{% endif %}
</div>
</body>
</html>
show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示界面</title>
</head>
<body>
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
{% for k in data %}
<tr>
{% for j in k %}
<td align="center" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
{% endfor %}
</table>
</body>
</html>
服务器端
GPRS端通过端口SOCKET传输数据,服务器端通过AJAX发送定时请求,接收SOCKET数据,并通过ORM存入数据库中,浏览器端可以查询数据。
urls.py
"""temperature URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path
from tempapp import views
app_name ='tempapp'
urlpatterns = [
path('', views.index, name='index'),
path('recvdata/', views.recvdata),
path('select/', views.select,name='select'),
path('show/',views.show,name='show'),
path('newest/',views.newest,name='newest'),
]
views.py
from django.shortcuts import render
from django.db import connection
from .models import temp
from django.shortcuts import render, HttpResponse, redirect, reverse
import socket
import time
def recvdata(request):
#接收一个GPRS数据
# if request.is_ajax():
# try:
# s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# # 接收数据的本机IP和端口号
# host = '127.0.0.1'
# port = 8000
# s.bind((host, port))
# # 接收数据
# data = s.recv(1024)
# print(data)
# data = str(data, encoding='utf-8')
# data = data.split(' ')
# position = data[0] # 接收位置信息
# temperature = data[1] # 接收温度信息
# print(position, temperature)
# # 添加一条数据到数据库中
# temp_data = temp(position=position, temperature=temperature)
# temp_data.save()
# data = 'position = ' + str(position) + 'm'+' '+'temperature = ' + str(temperature)+'°'
# r= HttpResponse(data)
# return r
# except:
# data = '当前没有数据输入,请检查数据是否正在输入'
# r1 = HttpResponse(data)
# return r1
# else:
# return HttpResponse('NO AJAX')
#接收两个GPRS数据
if request.is_ajax():
try:
# s1套接字 用于接收位置信息
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 接收数据的本机IP和端口号
host = '127.0.0.1'
port = 8000
s1.bind((host, port))
# 接收数据
data1 = s1.recv(1024)
data1 = float(data1)
position = data1 # 接收位置信息
except:
position = "没有位置信息输入"
try:
# s2套接字 用于接收温度信息
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 接收数据的本机IP和端口号
host = '127.0.0.1'
port = 8100
s2.bind((host, port))
# 接收数据
data2 = s2.recv(1024)
data2 = float(data2)
temperature = data2 # 接收位置信息
except:
temperature = "没有温度信息输入"
if (temperature != "没有温度信息输入") and (position != "没有位置信息输入"):
# 添加一条数据到数据库中
temp_data = temp(position=position, temperature=temperature)
temp_data.save()
data = 'position = ' + str(position) + 'm'+' '+'temperature = ' + str(temperature)+'°'
elif (temperature != "没有温度信息输入") and (position == "没有位置信息输入"):
data = 'temperature = ' + str(temperature) + '°' + ' , '+ '没有位置信息输入'
elif (temperature == "没有温度信息输入") and (position != "没有位置信息输入"):
data = 'position = ' + str(position) + 'm' + ' , ' + '没有温度信息输入'
else:
data = 'AJAX初始化完毕,当前没有数据输入'
r = HttpResponse(data)
return r
else:
return HttpResponse('NO AJAX')
def get_cursor():
return connection.cursor()
def index(request):
context = {
'status':'点击按钮,等待AJAX请求初始化'
}
return render(request,'index.html',context)
def show(request):
cursor = get_cursor()
cursor.execute("select id,position,date_added,temperature from tempapp_temp")
data_temps = cursor.fetchall() # 数据库所有数据
length = len(data_temps)
context ={
'data' : data_temps,
'length' : length}
return render(request, 'show.html',context)
def newest(request):
cursor = get_cursor()
cursor.execute("select id,position,date_added,temperature from tempapp_temp")
data_temps = cursor.fetchall() # 数据库所有数据
length = len(data_temps)
data_temps = data_temps[length-1]
context ={
'data' : data_temps,
'length' : length}
return render(request, 'newest.html',context)
# 查询
def select(request):
if request.method == "POST":
id = request.POST.get('id')
position = request.POST.get('position')
temperature = request.POST.get('temperature')
date_added = request.POST.get('date_added')
if id:
temp_data = temp.objects.filter(id=id).first()
if position:
temp_data = temp.objects.filter(position=position).all()
if temperature:
temp_data = temp.objects.filter(temperature=temperature).all()
if date_added:
temp_data = temp.objects.filter(date_added=date_added).first()
if temp_data == None:
#NoneType
return HttpResponse("错误")
else:
temp_datas = []
print(temp_data)
try:
length = len(temp_data)
for temp1 in temp_data:
id = temp1.id
position = temp1.position
temperature = temp1.temperature
date_added = temp1.date_added
datas = [id,position,temperature,date_added]
temp_datas.append(datas)
print(temp_datas)
context = {
'data': temp_datas,
'length': length,
'msg': True,
}
except TypeError:
length=1
id = temp_data.id
position = temp_data.position
temperature = temp_data.temperature
date_added = temp_data.date_added
datas = [id, position, temperature, date_added]
temp_datas.append(datas)
context = {
'data': temp_datas,
'length': length,
'msg': True,
}
return render(request, 'select.html', context)
else:
context = {
'msg' : False,
}
return render(request, 'select.html', context)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!--<meta charset="UTF-8" http-equiv="refresh" content="1" >-->
<meta charset="UTF-8">
<title>服务器端</title>
<script type="text/javascript">
function show(){
window.open("{% url 'show' %}",'newwindow','height=400,width=1200');}
</script>
<script type="text/javascript">
function select(){
window.open("{% url 'select' %}",'newwindow','height=400,width=1200');}
</script>
<script type="text/javascript">
function newest(){
window.open("{% url 'newest' %}",'newwindow','height=400,width=1200');}
</script>
<script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
<!--AJAX轮询,每隔1s发送一个AJAX请求给recvdata-->
$(document).ready(function(){
$("#recv").click(function(){
document.getElementById("recv").setAttribute("disabled", true);
document.getElementById("recv").innerHTML="数据正在接收中";
setInterval(function () {
$.get("/recvdata/", function(ret) {
$('#data').html(ret)
})},1000)
});
});
</script>
<style type="text/css">
body{
height:100%;
width:100%;
overflow: hidden;
}
</style>
<style>
.box1{
padding: 10px 10px;
width:100%;
height:400px;
border:5px solid #F0F0F0;
text-align:center;
background-color:rgba(0,0,0,0.3);
}
div{
text-align:center;
}
p{
font-size:200%;
color:black;
font-weight:bold
}
h1{
font-size:500%;
color:#787878;
}
.button {
background-color: #404040; /* Blue */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 20px;
border-radius: 8px;
border: 5px solid white;
}
hr{height:5px;border:none;border-top:5px ridge black;width:80%}
</style>
</head>
<body >
<br>
<h1 align="center" >欢迎来到温度管理系统服务器端</h1><br>
<div align="center" class="box1" >
<p>
<form action="/recvdata/" method="get">
<p><span id="data">{{status}}</span></p>
<button type="button" id="recv">请点击开始接收数据</button>
</form>
</p>
<hr>
<p> 请选择功能 </p>
<button type="button" class="button" onclick="show()">展示所有数据</button>
<button type="button" class="button" onclick="select()">检索数据</button>
<button type="button" class="button" onclick="newest()">展示最新数据</button>
</div>
</body>
</html>
newest.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>最新数据</title>
</head>
<body>
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
<tr>
{% for j in data %}
<td align="center" id="lastdata" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
</table>
</body>
</html>
select.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" >
<title>检索界面</title>
</head>
<style type="text/css">
body{
height:100%;
width:100%;
overflow: hidden;
background-color: rgba(0,0,0,0.1);
}
h1{
font-size:400%;
color:black;
}
h2{
font-size:200%;
color:black;
}
h3{
font-size:100%;
color:red;
}
input[type=text], select {
width: 50%;
padding: 20px 20px;
margin: 8px 0;
<!--display: inline-block;-->
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 10%;
background-color: #4CAF50;
color: white;
padding: 20px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[value="查询"] {
font-size:80%;
}
input[type=submit]:hover {
background-color: #45a049;
}
.div{float:middle;}
form{
font-size:150%;
}
}
</style>
<body style="overflow:auto;">
<h1 align="center">检索界面</h1>
<div class="div">
{% if not msg %}
<h2 align="center">根据ID来查询温度</h2>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form1' action="/select/" align="center" >
{% csrf_token %}
ID:<input type="text" name="id" placeholder={{ id }}>
<input class="bc" type="submit" value="查询" align="center">
</form>
<br>
<hr>
<br>
<h2 align="center">根据位置来查询温度</h2>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form2' action="/select/" align="center">
{% csrf_token %}
位置:<input type="text" name="position" placeholder={{ position }}>
<input class="bc" type="submit" value="查询">
</form>
<br>
<hr>
<br>
<h2 align="center">根据时间来查询温度 格式如下</h2>
<h3 align="center" >2019-11-04 02:10:24</h3>
{# 判断是否由msg这个参数,或者判断其值,没有的话则执行这段代码#}
<form method="post" class='form3' action="/select/" align="center">
{% csrf_token %}
时间:<input type="text" name="date_added" placeholder={{ date_added }}>
<input class="bc" type="submit" value="查询" >
</form>
{% else %}
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
{% for k in data %}
<tr>
{% for j in k %}
<td align="center" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
{% endfor %}
</table>
{% endif %}
</div>
</body>
</html>
show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示界面</title>
</head>
<body>
<table width=100% height="150" align="center" border="2" bordercolor=black
cellspacing="10" cellpadding="10" >
<th align="center">序号</th>
<th align="center">位置</th>
<th align="center">时间</th>
<th align="center">温度</th>
{% for k in data %}
<tr>
{% for j in k %}
<td align="center" style="font-weight:bold">{{ j }}</td>
{% endfor %}
<tr>
{% endfor %}
</table>
</body>
</html>
models.py 和 setting.py都和客户端一样