Django实战(自定义模块+Echart Tree+sqlite3)

2023-05-16

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要从以下这些方面依次介绍这次django实战经验:

  • 数据处理
  • django基本框架搭建
  • sqlite3数据库
  • Json数据
  • Echart树状图
  • Jquery 异步刷新
  • laydate 日期查询
  • 前后端交互

数据处理

从本地文件夹中获得所有源文件,使用pandas进行数据的读取与清洗,得到两个dataframe数据。将这两组Dataframe数据写入sqlite3数据库的两个表格中,并生成Echart tree map所需的json文件。使用spyder调试无误后,封装为自定义模块,为后续django调用做准备。

需要注意的一点是,如果打算通过django直接调用python自定义模块,需要将已经写好的自定义模块放入projectname/myapp/management/commands/文件目录下,已“from .modulefilename import modulename”方法导入本地

Django基本构架搭建

比较基础的django构架搭建方法在此不再重复。

1. models.py 定义数据模型

from django.db import models

# Create your models here.
class Cleanliness(models.Model):
    Index = models.IntegerField(primary_key=True)
    Standard = models.CharField(max_length=50)
    Nr = models.CharField(max_length=50)
    Time = models.DateTimeField()
    Result = models.CharField(max_length=20)

class Opllist(models.Model):
    Index = models.IntegerField(primary_key=True)
    Date = models.DateTimeField()
    Findings = models.CharField(max_length=50)
    Responsible = models.CharField(max_length=20)
    Station = models.CharField(max_length=20)
    Category = models.CharField(max_length=10)
    Risk = models.CharField(max_length=10)

数据库的写入与覆盖操作是使用如下模块执行的,网上对于这个方法有详细的介绍,其中也说过如果是数据库表格的覆盖操作,不建议使用这个方法的replace进行整体替代,而是推荐使用数据库本身的is_deleted方法进行,目前没有尝试过。但如果使用的是to_sql的replace方法,在models.py定义模型时,必须定义主键primary_key,否则在后期调试过程中,会出现数据无法写入数据库的错误。

    #连接到数据库
    #数据库文件是“test.db”
    #如果数据库不存在的话,将会自动创建一个 数据库
    db = sqlite3.connect(r"C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\cleanliness.db")
    pd.io.sql.to_sql(df,"myapp_cleanliness",con=db,index=True,if_exists="replace")
    print('df-success!')
    db.close()

2. urls

url.py文件定义如下
from django.urls import path
from . import views  #.意味着当前目录

urlpatterns = [
    path('',views.index),   #url(r'^$',views.index)
    path('frame/',views.frame),
    path('time/',views.time),
    path('refresh/',views.refresh),
    path('opl_chart/',views.opl_chart),
]

3. setting.py
setting.py文件配置,设置DATABASES建立与sqlite3数据库的连接, Static设置确保能够正确引用静态文件。

# 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',
    'myapp',
]

ROOT_URLCONF = 'VSDproject.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',
            ],
        },
    },
]

# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'cleanliness.db'),
    }
}

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]

__4. views.py __
Django直接调用自定义模块,在views.py中进行引用 from .management.commands.duoxiancheng import mainfunction

在处理echart所需的json文件时,并没有根据数据库数据再形成json文件,而是通过自定义模块,对DataFrame数据进行处理,先根据treemap的要求生成字典结构的数据,然后再使用

 with open(r'C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\treedata.json', 'w') as f:
        json.dump(tree_data, f)

这样相当于把tree_data文件单独存放在一个指定位置,在views后端调用时,对应如下代码进行读取,然后再传递给前端。

    with open(r'C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\treedata.json', 'r') as f:
        tree_data = json.load(f)
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
import os
import json
from .management.commands.duoxiancheng import mainfunction

from .models import Cleanliness
from .models import Opllist
# 主页
def frame(request):
    with open(r'C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\treedata.json', 'r') as f:
        tree_data = json.load(f)
    partlist = Cleanliness.objects.all().order_by('-Time')
    opl_list = Opllist.objects.all().order_by('-Date')
    return render(request,'myapp/frame.html',{'parts':partlist,'opls':opl_list,'treedata':json.dumps(tree_data)})
# 查询后异步刷新页面
def refresh(request):
    runner = request.POST['select1']
    mainfunction(runner) 
    with open(r'C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\treedata.json', 'r') as f:
        tree_data = json.load(f)
    partlist = Cleanliness.objects.all()
    return render(request,'myapp/refresh.html',{'parts':partlist,'treedata':json.dumps(tree_data)})
# opl表格异步刷新
def opl_chart(request):
    name = request.POST['select']
    opl_list_filter = Opllist.objects.filter(Station = name[2:6]).filter(Category=name[0]).order_by('-Date')
    return render(request,'myapp/opl_chart.html',{'opls':opl_list_filter})

sqlite3数据库

sqlite3数据库是django自带的轻量级数据库,对于目前这个案例的使用程度,数据量小,数据库调用简单,sqlite3完全可以胜任,而且在settings.py配置时,也比较简单,在自定义模块中的写入和覆盖操作都比较简单。其语法和mysql差别不大。掌握一个数据库的基本用法后,其它的数据库的基本用法可以类推。

Json数据

Echart treemap需要向前端传递Json格式的数据,在自定义模块中根据树状图结构对需要展示的数据进行结构搭建。具体要求可以查看Echart官方文档。

Echart Tree Map

对于树状图的其它介绍echarts中树形结构图(参数分析)
建议啃官方文档Echart官方文档
下载echarts.min.js文件后,放入static/myapp/js/路径下,在html文件中,使用
后端views配置如下,将json数据得到后,放入tree_data,传入前端。

def refresh(request):
    print('run!')
    runner = request.POST['select1']
    mainfunction(runner) 
    print(runner)
    with open(r'C:\Users\WAY1QIN\Desktop\Usecase\cleanliness VSD\VSD\VSDproject\treedata.json', 'r') as f:
        tree_data = json.load(f)
    partlist = Cleanliness.objects.all()
    return render(request,'myapp/refresh.html',{'parts':partlist,'treedata':json.dumps(tree_data)})
进行引用。
 <script type="text/javascript" src="/static/myapp/js/echarts.min.js"></script>
            <div id="tree_chart" style="widows: 400px;">
                
                <!-- 引入tree_chart实现数据树状图显示 -->
                <script type="text/javascript">
                var treedata = {{ treedata|safe }}
                var myChart=echarts.init(document.getElementById('tree_chart'))
                myChart.setOption(option = {
                tooltip: {
                    //show:'true',//默认:true;是否显示提示框组件,包括提示框浮层和 axisPointer。
                    trigger: 'item',//默认:item;触发类型。item:数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。'axis':坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。'none':什么都不触发。
                    triggerOn: 'mousemove',
                },
                series:[
                    {
                        type: 'tree',
                        data: [treedata],
                        left: '20%',
                        right: '30%',
                        top: '5%',
                        bottom: '20%',
                        symbol: 'circle',
                        orient: 'LR',
                        height:"80%",
                        expandAndCollapse: true,//默认:true;子树折叠和展开的交互,默认打开 。           
                        initialTreeDepth:3,//默认:2,树图初始展开的层级(深度)。根节点是第 0 层,然后是第 1 层、第 2 层,... ,直到叶子节点           
                        label: {
                            normal: {
                                position: 'top',//标签的位置。
                                rotate: 0,//标签旋转。从 -90 度到 90 度。正值是逆时针。
                                verticalAlign: 'middle',//文字垂直对齐方式,默认自动。
                                align: 'right',//文字水平对齐方式,默认自动。
                                fontSize: 12,//文字的字体大小
                            },
                        },            
                        symbolSize:12,  //节点大小,默认10         
                        leaves: {
                            label: {
                                normal: {
                                    position: 'right',
                                    rotate: 0,
                                    verticalAlign: 'middle',
                                    align: 'left',
                                    fontSize: 12,//文字的字体大小
                                }
                            }
                        },
        
                        lineStyle: {
                            curveness:0.5,
                        },                          
                        itemStyle:{
                            normal:{
                                color:function(params){
                                    var colorList = ['green','yellow','red']
                                    // console.dir(params.value)
                                    return colorList[params.value]
                                },
                            borderColor:'black',
                            // color: 'yellow',
                            
                            },
                        },           
                        animationDurationUpdate: 750,           
                    }
                ]
                }
                );
                //防止重复触发点击事件
                if(myChart._$handlers.click)
                {
                    myChart._$handlers.click.length = 0;
                }
                //使用ajax异步刷新表格数据,通过click事件,触发刷新
                myChart.on('click',  function(param) {
                    var par = [param.data.name,param.data.station]
                    if(par[0].length>1){
                        $.ajax({
                        type:'POST',  //方式为POST
                        url:'/time/', //设置刷新后表格的url
                        data:{'select':param.name},
                        dataType:'text',
                        success:function(data) //如果异步成功,执行下面代码
                        {
                            //alert(param.name);弹出窗口
                            // location.reload();重新加载页面,不需要,暂时隐藏
                            $('#table').html(data);
                        }
                        })  
                    }
                    if(par[0].length==1){
                        var strpar = par.toString()
                        console.log(strpar)
                        $.ajax({
                        type:'POST',  //方式为POST
                        url:'/opl_chart/', //设置刷新后表格的url
                        data:{'select':strpar},
                        dataType:'text',
                        success:function(data) //如果异步成功,执行下面代码
                        {
                            //alert(param.name);弹出窗口
                            // location.reload();重新加载页面,不需要,暂时隐藏
                            $('#table1').html(data);
                        }
                        })
                    }
                    //var par
                    console.log(par)

                // console.dir(param.name)
                    })
                </script>
            </div>

Jquery 异步刷新

上面代码中,已经包含异步刷新的过程,相关的其它介绍可以搜以下,文章很多,本例中使用异步刷新之前。也做了一些定义,由于我的目标是点击树状图节点可以触发不同的表格进行异步刷新,这就意味这先得判断要触发哪一个表格,所以,在最开始定义tree图用的json数据时,我就把一个表格信息写入了不同的字典层级中,当点击节点后,拿到节点属性,根据表格信息来做if判断,判断要触发哪一个异步刷新,然后再去调用相关的html文件。并将数据从前端传递给后端。

def opl_chart(request):
    name = request.POST['select']
    opl_list_filter = Opllist.objects.filter(Station = name[2:6]).filter(Category=name[0]).order_by('-Date')
    return render(request,'myapp/opl_chart.html',{'opls':opl_list_filter})

def time(request):
    name = request.POST['select']
    partlist_filter = Cleanliness.objects.filter(Standard = str(name)).order_by('-Time')
    return render(request,'myapp/time.html',{'parts1':partlist_filter})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>

</script>
</head>
<body>

    <table id='table1'>
        <tr>
        <th>Date</th>
        <th>Findings</th>
        <th>Resp</th>
        <th>Station</th>
        </tr>
    <ul>
        {%for opl in opls%}
    
        <tr>
        <td>{{opl.Date}}</td>
        <td>{{opl.Findings}}</td>
        <td>{{opl.Responsible}}</td>
        <td>{{opl.Station}}</td>
        </tr>

        {% endfor %}

    </ul>
    </table>


</body>
</html>

鼠标所点击的节点属性可以通过下面得到

<script type="text/javascript" src="/static/myapp/js/jquery-3.5.1.min.js"></script>

 //使用ajax异步刷新表格数据,通过click事件,触发刷新
      myChart.on('click',  function(param){}

如果异步刷新出现权限问题时,记得在要刷新的语句前加上

$.ajaxSetup({
      data:{csrfmiddlewaretoken:'{{ csrf_token }}'}
  })

laydate 日期查询

下载laydate.js, 放在static/laydate目录下,并使用异步刷新,这样在选中日期后,将选择的日期以POST的形式传给后端,并对整个页面进行刷新。

 <script>
                function getdata(){
                    var text = document.getElementById("test1");
                    console.log(text.value)
                    $.ajax({
                        type:'POST',  //方式为POST
                        url:'/refresh/', //设置刷新后表格的url
                        data:{'select1':text.value},
                        dataType:'text',
                        success:function(data){ //如果异步成功,执行下面代码
                            //console('success!');//弹出窗口
                            // location.reload();重新加载页面,不需要,暂时隐藏
                            $('box').html(data)
                        }
                    })
                }
                
                $.ajaxSetup({
                    data:{csrfmiddlewaretoken:'{{ csrf_token }}'}
                })
            </script>
            <input type="text" id='test1'>
            <button id='btn' onclick="getdata()">Search</button>
    
            <script src="/static/laydate/laydate.js"></script>
            <script>
                //执行一个laydate实例
                laydate.render({
                    elem:'#test1', //指定元素
                    range:true,
                });
            </script>

效果如下:
在这里插入图片描述

前后端交互

前后端交互的大部分方法都可以搜过相关文章找到,关于自定义模块的刷新,可以在views.py中引入自定义模块执行语句,来进行刷新,也可以在前端设置button,将button触发指令传递给后端,来调用自定义模块。表格和tree图的交互,主要是组合数据库的查询指令实现的,将所有数据清洗写入数据库后,可以实现快速刷新,而且不必再次执行自定义模块,可以加快程序运行。

断断续续的写了这个程序,最终也没有正式使用,但在这个过程中,自己是对django进行了一次实践,学习到了不少东西。第一次搭建,难免会有很多不是最优的地方,但至少功能是实现了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django实战(自定义模块+Echart Tree+sqlite3) 的相关文章

  • 如何覆盖 Django 的默认管理模板和布局

    我正在尝试覆盖 Django 的默认模板 现在只有base site html 我正在尝试更改 django 管理文本 我做了以下事情 我在我的应用程序目录中创建了一个文件夹 opt mydjangoapp templates admin
  • 将 transaction.commit_manually() 升级到 Django > 1.6

    我继承了为 Django 1 4 编写的应用程序的一些代码 我们需要更新代码库以使用 Django 1 7 并最终更新到 1 8 作为下一个长期支持版本 在一些地方它使用旧风格 transaction commit manually and
  • 从 S3 提供 Django 的静态文件和媒体文件

    我遇到了一个奇怪的问题 我不知道是什么原因造成的 这是我当前的配置 使用Heroku MEDIA URL media STATIC URL static STATICFILES DIRS os path join PROJECT DIR s
  • Django Rest Framework 删除 csrf

    我知道有关于 Django Rest Framework 的答案 但我找不到解决我的问题的方法 我有一个具有身份验证和一些功能的应用程序 我向其中添加了一个新应用程序 它使用 Django Rest Framework 我只想在这个应用程序
  • 在 Bootstrap 中使单击的选项卡处于活动状态

    我正在使用 Django 并将 Bootstrap 与 Django 集成 这是我的导航栏 HTML 代码 div class navbar navbar default navbar fixed top div class contain
  • 如何在Django项目中使用PostgreSQL的存储过程或函数

    我正在开发一个 Django 项目 我决定在 PostgreSQL 中编写逻辑代码 而不是用 Python 编写 因此 我在 PostgreSQL 中创建了一个存储过程 例如 存储过程如下所示 create or replace proce
  • Django:测试客户端的上下文在 shell 中为空

    我无法访问context的属性HttpResponse来自 ipython 的对象 但单元测试访问context 这是单元测试 测试运行正常通过 from django test import Client TestCase from dj
  • Django“和”Pinax 还是只是 Pinax?

    我正在开发一个个人项目 该项目已 完成 但现在我想添加一个社交应用程序 我认为 Pinax 已经为这项任务做好了准备 我想知道一些事情 我可以在我的项目中像 django 应用程序一样使用 pinax 吗 或者我需要使用 pinax 重新设
  • 如何删除 Django 中的模型元排序或从内置管理器获取原始查询集?

    我有一个模型 它使用元排序属性来确保使用它的所有视图以相同的顺序显示内容 但是 我有一种方法需要使用distinct 方法 应用订购后此方法不起作用 是否有一种内置方法可以在应用排序之前检索原始查询集 或者我是否需要编写一个自定义管理器类来
  • 在 Django 模板中使用 forloop.counter 值作为列表索引

    在我的 Django 1 1 1 应用程序中 我在视图中有一个函数 它向模板返回一系列数字和项目列表列表 例如 data item1 item2 item3 item4 item5 item6 item7 item8 item9 retur
  • Django 的内联管理:一个“预填充”字段

    我正在开发我的第一个 Django 项目 我希望用户能够在管理中创建自定义表单 并向其中添加字段当他或她需要它们时 为此 我在我的项目中添加了一个可重用的应用程序 可在 github 上找到 https github com stephen
  • 带有用户信息的 Django Logger

    我只是好奇 是否可以放User内的信息formatters信息输入LOGGING配置在setting py 现在我只是将该信息放入要记录的消息中 但也许有一种方法可以将其设置为formatters争论 这是我的LOGGING现在的配置 LO
  • Pickle django 查询?

    是否可以在数据库中腌制或以某种方式存储 django 查询 这是行不通的 u User objects all import cPickle pickled query cPickle dumps u and store the pickl
  • Django - 从缓存的查询中填充模型实例相关字段

    情况相同Django prefetch children 相关的children https stackoverflow com questions 55201573 django prefetch related children of
  • django-orm:如何更新一对一关系字段值

    模型 py class Area models Model area name models CharField max length 255 null False blank False description models TextFi
  • Redis+Docker+Django - 错误 111 连接被拒绝

    我正在尝试使用 Redis 作为使用 Docker Compose 的 Django 项目的 Celery 代理 我无法弄清楚我到底做错了什么 但尽管控制台日志消息告诉我 Redis 正在运行并接受连接 事实上 当我这样做时 docker
  • django 模板 - 如何动态访问变量?

    假设我有一个具有以下上下文的 django 模板 data1 this is data1 data2 this is data2 data name data2 现在我知道了data name 假设它是 data2 是否可以用它来访问变量d
  • Django 多对多关系(类别)

    我的目标是向我的 Post 模型添加类别 我希望以后能够按不同类别 有时是多个类别 查询所有帖子 模型 py class Category models Model categories 1 red 2 blue 3 black title
  • Django - 使用“@api_view”将 Django Rest Swagger 架构添加到 DRF 标记函数

    Django 如何将 swagger 自动模式添加到 DRF 标记函数 api view 我有这个功能 view py api view POST swagger auto schema request body PostSerialize
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour

随机推荐