还是带着实际项目来搭建Django框架吧。本项目已经测试,效果演示如下:
背景:假如有两台设备,分别为core_making和mixer,对应两台PLC,一台S7-1500,另一台S7-1200。两台PLC完全独立,之间没有建立任何通讯,因此项目必须对两台PLC同时进行通讯。
任务:每台PLC既可以有独自对应的网页来监控,也可以实现一个页面同时读写两台PLC的数据。
分析:每台设备监控的数据分开管理,不易混淆,因此Django项目建立两个app应用,分别为core_making和mixer。
开篇前,先罗列几个基本概念和常用命令:
Django核心思想:MVT,解耦。
M:model,模型,负责与数据库交互
V:view,视图是核心,负责接收请求、获取数据、返回结果
T:template,模板,负责呈现内容到浏览器
Django命令:
创建项目:django-admin startproject 项目名称
创建应用:python manage.py startapp 应用名称
开启简易服务器:python manage.py runserver
生成迁移文件:python manage.py makemigrations
执行迁移:python manage.py migrate
项目的目录说明:
manage.py:命令行工具,可以与Django项目进行交互
项目同名目录:项目的Python包
_init _.py:空文件,可以当做包被导入
settings.py:项目整体配置文件
urls.py:项目的URL入口
wsgi.py:项目与WSGI Web服务器入口
App的目录说明:
migrations:模型迁移时,迁移文件的存放路径及执行迁移时的数据源
admin.py:注册模型,后台站点管理
models.py:是处理数据的,MVT中的M
tests.py:测试
views.py:处理业务逻辑,MVT中的V
正篇:
先搭建Django框架,建议在Pycharm下完成所有的搭建步骤,可以省去几个需要手动添加或设置的地方。
一、创建Django工程
新建Django项目CoreCenter,同时创建应用core_making
1、项目下自动生成templates文件夹
2、core_making应用下的apps.py自动包含以下代码:
from django.apps import AppConfigclass CoreMakingConfig(AppConfig): name = 'core_making'
二、创建第二个应用mixer
mixer应用下的apps.py自动包含以下代码:
from django.apps import AppConfigclass MixerConfig(AppConfig): name = 'mixer'
三、App应用注册
创建App应用后需要在项目的同名文件夹中的settings.py文件中注册
# settings.pyINSTALLED_APPS = [ 'django.contrib.admin', # 站点管理系统 'django.contrib.auth', # 认证系统 'django.contrib.contenttypes', # content types框架 'django.contrib.sessions', # session框架 'django.contrib.messages', # message框架 'django.contrib.staticfiles', # 静态文件管理框架 'core_making.apps.CoreMakingConfig', # 已经自动注册,创建项目和首个应用时自动产生 'mixer.apps.MixerConfig', # 需手动注册,创建第二个应用时,并没有自动产生]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', ], }, },]
四、urls配置
1、如上图所示,还需要分别在core_making和mixer两个APP下,建立各自的urls.py文件。
必须注意的是:django2.0在url的配置上较之以前的版本有点区别,在之前的版本是通过django.conf.urls.url函数来实现路径配置的。
urlpatterns = [ url(r'index/',views.index),]
在2.0+版本中,通过django.urls.path函数来配置。
urlpatterns = [ path("index/",views.index)]
写法上的区别如下:
url(r'^index/$',views.index),path('index/',views.index),
如上,url 支持正则写法。path如果要使用正则,则要引入re_path
from django.urls import path, re_path
2、项目下urls如何管理多个App下的urls
core_making下的uls.py
from django.urls import pathfrom . import viewsurlpatterns = [ path('read_ajax/', views.read_ajax), path('double/', views.double),]
mixer下的uls.py
from django.urls import pathfrom . import viewsurlpatterns = [ path('read_ajax/', views.read_ajax),]
项目CoreCenter下的urls.py
from django.contrib import adminfrom django.urls import path, includefrom core_making import viewsurlpatterns = [ path('admin/', admin.site.urls), path('core/', include('core_making.urls')), path('mixer/', include('mixer.urls')),]
3、设置成功后,输入两级地址:
127.0.0.1:8000/core/double
考虑到该任务还没有必要建立数据库,到此已经可以开始测试。因此搭建步骤就分上下篇总结,上篇到此告一段落,下篇总结模型设计和迁移。
五、业务逻辑
1、 在core_making下的views.py
from django.shortcuts import render, HttpResponseimport jsonimport snap7from CoreCenter import S7WL_rw, bit_rwplc_1500 = snap7.client.Client()plc_1500.connect('192.168.0.12', 0, 1)def double(request): return render(request, 'doubledisplay.html')def read_ajax(request): core_value = S7WL_rw.ReadReal(plc_1500, "DBD", 1, 38) ret = {'core_value': core_value} return HttpResponse(json.dumps(ret))
2、在mixer下的views.py
from django.shortcuts import render, HttpResponseimport jsonimport snap7from CoreCenter import S7WL_rw, bit_rwplc_1200 = snap7.client.Client()plc_1200.connect('192.168.0.11', 0, 1)def read_ajax(request): mixer_value = S7WL_rw.ReadInt(plc_1200, 'MB', 0, 10) ret = {'mixer_value': mixer_value} return HttpResponse(json.dumps(ret))
六、模板
新建doubledisplay.html
<html lang="en"><head> <meta charset="UTF-8"> <title>多台PLC监测title>head><body> <label for="display_core">CoreMaking PLC S7-1500传过来的实时值:label> <span id="display_core">span> <label for="display_mixer">Mixer PLC S7-1200传过来的实时值:label> <span id="display_mixer">span> <script src="/static/js/jquery-3.5.1.min.js">script> <script src="/static/js/highcharts.js">script> <div id="container" style="width: 1000px; height: 400px; margin: 0 auto">div> <script language="JavaScript"> $(document).ready(function() { let chart = { type: 'spline', animation: Highcharts.svg, marginRight: 10, events: { load: function () { let series = this.series[0]; setInterval(function () { $.ajax({ url: "/core/read_ajax/", type: 'POST', data: {}, success: function (data) { let obj = JSON.parse(data); let core_value = obj.core_value; document.getElementById('display_core').innerHTML = core_value; let x = (new Date()).getTime(), y = core_value; series.addPoint([x, y], true, true); } }); $.ajax({ url: "/mixer/read_ajax/", type: 'POST', data: {}, success: function (data) { let obj = JSON.parse(data); let mixer_value = obj.mixer_value; document.getElementById('display_mixer').innerHTML = mixer_value; } }); }, 1000); } } }; let title = { text: '光电测距实时值' }; let xAxis = { type: 'datetime', tickPixelInterval: 150 }; let yAxis = { title: { text: 'Value' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }; let tooltip = { formatter: function () { return '' + this.series.name + '
' + Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '
' + Highcharts.numberFormat(this.y, 2); } }; let plotOptions = { area: { pointStart: 1940, marker: { enabled: false, symbol: 'circle', radius: 2, states: { hover: { enabled: true } } } } }; let legend = { enabled: false }; let exporting = { enabled: false }; let series= [{ name: 'DB1.DBD38', data: (function () { let data = [],time = (new Date()).getTime(),i; for (i = -19; i <= 0; i += 1) { data.push({ x: time + i * 1000, y: Math.random() }); } return data; }()) }]; let json = {}; json.chart = chart; json.title = title; json.tooltip = tooltip; json.xAxis = xAxis; json.yAxis = yAxis; json.legend = legend; json.exporting = exporting; json.series = series; json.plotOptions = plotOptions; Highcharts.setOptions({ global: { useUTC: false } }); $('#container').highcharts(json); });script>body>html>
七、项目演示
返回篇首查看。