【问题标题】:Django interactive web plotsDjango 交互式网络图
【发布时间】:2016-05-22 17:19:00
【问题描述】:

我只是想知道使用 Django 为网站创建交互式绘图的最佳方法是什么。当用户更改方程参数时,绘图需要交互更改。有什么推荐的套餐吗?

【问题讨论】:

    标签: python django plot interactive


    【解决方案1】:

    我会使用 Highcharts,然后你需要创建 django 后端,以便将数据存储到数据库或其他东西中......

    这是我为学校所做的一个例子:

    glucose.html:

    {% extends "base.html" %}
    
    {% block title %}Blood Glucose{% endblock %}
    
    {% block appmedia %}{{glucose_form.media}}{% endblock %}
    
    {% block sidebar %}
        <li data-toggle="collapse" data-target="#reading" class="collapsed">
            <a href="#">Add New Reading</a>
        </li>
        <ul class="sub-menu collapse" id="reading">
            <form id="glucose_form" action="/glucose/submit" method="POST">
                {% csrf_token %}
                {{ glucose_form.as_p }}
            </form>
            <button type="submit" id="glucose_submit">Submit</button>
        </ul>
        <li data-toggle="collapse" data-target="#settings" class="collapsed">
            <a href="#">Update Alert Settings</a>
        </li>
        <ul class="sub-menu collapse" id="settings">
            <form id="glucose_boundary_form" action="/glucose/goals" method="POST">
                {% csrf_token %}
                {{ glucose_boundary_form.as_p }}
            </form>
            <button type="submit" id="glucose_goals">Submit</button>
        </ul>
    {% endblock %}
    
    {% block content %}
    {{ glucose_result }}
        <div id="glucose_chart" style="width:100%; height:75%;"></div>
    
        <script type="text/javascript" >
            var chart = $('#glucose_chart').highcharts({
                chart: {
                    type: 'line'
                },
                title: {
                    text: 'Blood Glucose'
                },
                xAxis: {
                    type: 'datetime',
                    dateTimeLabelFormats: {
                        minute: '%l:%M %p',
                        hour: '%l %p',
                        day: '%b %d<br>%Y',
                        week: '%b %d<br>%Y',
                        month: '%b %Y',
                        year: '%Y'
                    },
                    title:{
                        text: null
                    },
                },
                yAxis: {
                    type: 'integer',
                    title:{
                        text: null
                    },
                    min: 0,
                    max: {{ glucose_boundary.upper_bound }} * 1.5,
                    ceiling: {{ glucose_boundary.upper_bound }} * 1.5,
                    gridLineWidth: 0,
                    plotBands: [{
                        id: 'upper_bound',
                        color: 'red',
                        from: '{{ glucose_boundary.upper_bound }}',
                        to: {{ glucose_boundary.upper_bound }} * 1.5,
                    },
                    {
                        id: 'lower_bound',
                        color: 'red',
                        from: '{{ glucose_boundary.lower_bound }}',
                        to: 0,
                    }],
                    plotLines: [{
                        id: 'goal_line',
                        color: 'lime',
                        value: '{{ glucose_boundary.glucose_goal }}',
                        width: 2
                    }]
                },
                plotOptions: {
                    series: {
                        states: {
                            hover: {
                                enabled: false
                            }
                        }
                    },
                    spline: {
                        marker: {
                            enabled: true
                        }
                    }
                },
                series: [{
                    color: 'blue',
                    showInLegend: false,
                    data: [
                        {% for result in glucose_results %}
                            {
                                'name': 'Result',
                                'x': Date.UTC(
                                    {{result.date_time.year}},
                                    ({{result.date_time.month}} - 1),
                                    {{result.date_time.day}},
                                    {{result.date_time.hour}},
                                    {{result.date_time.minute}}
                                ),
                                'y': {{result.glucose}},
                            },
                        {% endfor %}
                    ]
                }],
                tooltip: {
                    formatter: function() {
                    foods = this.point.name.replace(new RegExp('&lt;br&gt;', 'g'), '<br>');
                    timestamp = new Date(this.point.x).toLocaleFormat('%b %d, %Y');
                    return '<b><i>' + timestamp + ': ' + this.point.y + ' Calories</i></b><br><br>' + foods;
                  }
                },
                credits: {
                    enabled: false
                }
            });
            $('button#glucose_submit').click(function() {
                $.ajax({
                    url:'glucose/submit',
                    type: 'POST',
                    data: $('form#glucose_form').serialize(),
                    success: function(data) {
                        document.getElementById("glucose_form").reset();
                    }
                });
            });
            $('button#glucose_goals').click(function() {
                $.ajax({
                    url:'glucose/goals',
                    type: 'POST',
                    data: $('form#glucose_boundary_form').serialize(),
                    success: function(data) {
                        var chart = $('#glucose_chart').highcharts();
                        chart.yAxis[0].removePlotBand('upper_bound')
                        chart.yAxis[0].addPlotBand({
                            id: 'upper_bound',
                            color: 'red',
                            from: document.getElementById('id_upper_bound').value,
                            to: document.getElementById('id_upper_bound').value * 1.5,
                        });
                        chart.yAxis[0].removePlotBand('lower_bound')
                        chart.yAxis[0].addPlotBand({
                            id: 'lower_bound',
                            color: 'red',
                            from: document.getElementById('id_lower_bound').value,
                            to: 0,
                        });
                        chart.yAxis[0].removePlotLine('goal_line')
                        chart.yAxis[0].addPlotLine({
                            id: 'goal_line',
                            color: 'lime',
                            value: document.getElementById('id_glucose_goal').value,
                            width: 2
                        });
                        chart.redraw();
                    }
                });
            });
            // ajax components
            function getCookie(name) {
                var cookieValue = null;
                if (document.cookie && document.cookie != '') {
                    var cookies = document.cookie.split(';');
                    for (var i = 0; i < cookies.length; i++) {
                        var cookie = jQuery.trim(cookies[i]);
                        // Does this cookie string begin with the name we want?
                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                            break;
                        }
                    }
                }
                return cookieValue;
            };
            var csrftoken = getCookie('csrftoken');
            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
            $.ajaxSetup({
                beforeSend: function(xhr, settings) {
                    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                        xhr.setRequestHeader("X-CSRFToken", csrftoken);
                    }
                }
            });
        </script>
            <style>
            #sidebar {background-color: d46a6a; width: 18%; border-radius: 10px; margin: 10px}
            a{color: #ffffff !important}
            .container-fluid {background-color: d46a6a !important; border-color: d46a6a !important}
            label{color: #ffffff}
            body{background-color: #aa3939}
            .navbar-header {background-color: d46a6a!important, border-color:d46a6a !important}
            #content{background-color: white; border-radius: 10px}
        </style>
    {% endblock %}
    

    这是我的views.py:

        from bgpal.models import *
    from bgpal.forms import *
    from datetime import datetime
    from django.db import transaction
    from django.shortcuts import render
    from django.core.urlresolvers import reverse
    from django.shortcuts import get_object_or_404
    from django.http import HttpResponse, HttpResponseRedirect
    from django.contrib.auth.decorators import login_required
    
    # Create your views here.
    def home(request):
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse('loginregistration.views.login'))
        return HttpResponseRedirect('glucose')
    
    @login_required
    def glucose(request):
        if request.method == 'GET':
            glucose_boundary = __get_glucose_boundary_or_create_initial(request)
            glucose_results = __get_glucose_points(request)
            glucose_boundary_data = {'upper_bound':glucose_boundary.upper_bound,
                                     'lower_bound':glucose_boundary.lower_bound,
                                     'glucose_goal':glucose_boundary.glucose_goal}
            glucose_boundary_form = BloodGlucoseBoundForm(initial=glucose_boundary_data)
            glucose_form = BloodGlucoseForm()
            payload = {'glucose_boundary':glucose_boundary, 'glucose_results':glucose_results,
                       'glucose_boundary_form':glucose_boundary_form, 'glucose_form':glucose_form}
            return render(request, 'glucose.html', payload)
    
    @login_required
    def glucose_submit_result(request):
        if request.method == 'POST':
            with transaction.atomic():
                try:
                    glucose = request.POST['glucose']
                    insulin_dosage = request.POST['insulin_dosage']
                    date_time = __get_datetime(request, 'date_time')
                    glucose_result = BloodGlucoseModel(user=request.user, glucose=glucose,
                                                    insulin_dosage=insulin_dosage, date_time=date_time)
                    glucose_result.save()
                    return HttpResponse("Success")
                except:
                    return HttpResponse("Failed")
        return HttpResponse("Failed")
    
    @login_required
    def glucose_update_result(request):
        if request.method == 'POST':
            with transaction.atomic():
                try:
                    glucose_result = get_object_or_404(BloodGlucoseModel, user=request.user, id=request.POST['id'])
                    glucose_result.glucose = request.POST['glucose']
                    glucose_result.insulin_dosage = request.POST['insulin_dosage']
                    glucose_result.date_time = request.POST['date_time']
                    glucose_result.save()
                    return HttpResponse("Success")
                except:
                    return HttpResponse("Failed")
        return HttpResponse("Failed")
    
    @login_required
    def glucose_remove_result(request):
        if request.method == 'POST':
            with transaction.atomic():
                try:
                    glucose_result = get_object_or_404(BloodGlucoseModel, user=request.user, id=request.POST['id'])
                    glucose_result.delete()
                    return HttpResponse("Success")
                except:
                    return HttpResponse("Failed")
        return HttpResponse("Failed")
    
    @login_required
    def glucose_update_goals(request):
        if request.method == 'POST':
            with transaction.atomic():
                try:
                    glucose_boundary = __get_glucose_boundary_or_create_initial(request)
                    glucose_boundary.upper_bound = request.POST['upper_bound']
                    glucose_boundary.lower_bound = request.POST['lower_bound']
                    glucose_boundary.glucose_goal = request.POST['glucose_goal']
                    glucose_boundary.save()
                    return HttpResponse("Success")
                except:
                    return HttpResponse("Failed")
        return HttpResponse("Failed")
    
    def __get_glucose_boundary_or_create_initial(request):
        glucose_boundary = BloodGlucoseBoundModel.objects.filter(user=request.user)
        if glucose_boundary:
            glucose_boundary = glucose_boundary[0]
        else:
            glucose_boundary = BloodGlucoseBoundModel(user=request.user, upper_bound=200,
                                                    lower_bound=50, glucose_goal=100)
            glucose_boundary.save()
        return glucose_boundary
    
    def __get_glucose_points(request):
        glucose_list =BloodGlucoseModel.objects.filter(user=request.user)
        glucose_list = glucose_list.order_by('date_time')
        glucose_points = []
        for sugar in glucose_list:
            date_time = datetime(sugar.date_time.year, sugar.date_time.month, sugar.date_time.day,sugar.date_time.hour,sugar.date_time.minute, sugar.date_time.second)
    
            glucose_points.append({'glucose': sugar.glucose, 'date_time': date_time})
    
        return glucose_points
    
    def __get_datetime(request, field_name):
        # Look here for datetime string format http://www.tutorialspoint.com/python/time_strptime.htm
        return datetime.strptime(request.POST[field_name], '%m/%d/%Y %I:%M %p')
    

    【讨论】:

      猜你喜欢
      • 2012-02-09
      • 2011-09-13
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多