【问题标题】:Django - Use AJAX to "stream" the results of a query set with annotationsDjango - 使用 AJAX “流式传输”带有注释的查询集的结果
【发布时间】:2019-07-16 07:25:48
【问题描述】:

所以我正在加载模型字段中存在的每个值的计数。一切正常,但我必须每次在数据库中进行更改时都重新启动服务器,以使更改在前端生效。

我认为 AJAX 可能适合这种事情,但我不知道如何去做。另请注意,在我的查询中,我有模板中使用的注释。

我的看法如下:

def counts(request):
    duplicates = Application.objects.all().filter(is_qualified="awarded").values('school_name').annotate(name_count=Count('school_name'))
    context = {
    'repeated_names' : records,
    'duplicates' : duplicates,
    'title' : 'Disbursement Details',
}

return render(request, 'calculations/list.html', context)

我的网址为:

path('list/', default_views.counts, name='count_rows'),

最后我的模板为:

<table class="table table-hover" id="disbursement_table">
         <thead class=" wow fadeInLeft">
            <tr>
                <th>#</th>
                <th>School</th>
                <th>Number of Applicants</th>

            </tr>
         </thead>
         <tbody class=" wow fadeInRight" wow-data-duration="2s">

            {% for application in duplicates %}

             <tr class="clickabe-row" data-target="{% url 'dup_detail' application.school_name %}">
                <td>{{ forloop.counter}}</td>
                <td>{{ application.school_name}}</td>
                <td>{{ application.name_count }}</td>
             </tr>

            {% endfor %}

         </tbody>
    </table>

每次数据库发生变化时,我是否可以使用 AJAX 定期更新 {{ application.name_count }} 值?

【问题讨论】:

    标签: ajax django django-views


    【解决方案1】:

    在我看来你有两个选择:

    1. 使用Channels,这是一个很棒的 Django Websockets 库:
      • Signals,这是原生 Django 功能,可以让您知道数据何时保存到模型中。
      • 那么只需要在javascript端实现Websocket通信即可,比较简单。

    signals.py 示例

    @receiver(post_save, sender=CanBusAnalyzerJob, dispatch_uid='update_job_status_listeners')
    def update_job_status_listeners(sender, instance, **kwargs):
        '''
        Sends job status to the browser when a Job is modified
        '''
        job_id = instance.job_id
        group_name = 'new-job-' + job_id
    
        message = {
            'total': instance.job_total,
            'progress': instance.progress,
            'status': instance.status
        }
    
        channel_layer = channels.layers.get_channel_layer()
    
        async_to_sync(channel_layer.group_send)(
            group_name,
            {
                'type': 'send_job_progress',
                'text': message
            }
        )
    

    JS代码测试websocket连接

    <script>
      var socket = new WebSocket('ws://' + window.location.host + '/ws/');
    
      socket.onopen = function() {
        console.log("Websocket connection done!");
    
        if (socket.readyState == WebSocket.OPEN) {
          setInterval(function() {
            socket.send('Hello World');
          }, 10000);
        }
      };
    
      socket.onmessage = function(e) {
        var data = JSON.parse(e.data);
        var message = data['message'];
        console.log(data);
      };
    
      socket.onclose = function(e) {
        console.error('Chat socket closed unexpectedly');
      };
    </script>
    

    对我来说这是可行的方法,但是如果您想要快速的东西,那么您可以创建一个视图并将其注册到 urls.py 文件中,该文件将每隔 X 秒从您的前端代码调用一次。这将从数据库中获取新数据并已返回 html 代码,或者仅返回数据并在 JS 代码中对其进行处理。

    views.py
    如果你需要,这个例子也可以接收 POST 参数,like 和 ID(名称在 urls.py 文件中设置)。如果您只需要获取数据删除第三行。

    class ToggleFavouriteSignalView(View):
        def post(self, request, *args, **kwargs):
            obj_id = kwargs['signal_id']
    
            try:
                model_obj = CanBusLogAnalyzer.objects.get(id=obj_id)
    
                new_val = False if model_obj.favourite else True
    
                model_obj.favourite = new_val
                model_obj.save()
    
                response_text = 'Success:Signal setted as favourite.' if new_val else 'Info:Signal removed as favourite.'
    
                return HttpResponse(response_text, status=200)
            except CanBusLogAnalyzer.DoesNotExist:
                return HttpResponse('Error:The object no longer exists in the database.', status=503)
            except Exception:
                return HttpResponse('Error:Please check your internet connection.', status=503)
    

    JS 代码

    //For authentication purposes
    function getCrsfCookie() {
        var cookieValue = null,
            name = 'csrftoken';
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    
    //Runs every 5 seconds
    setInterval(function() {
        var csrfcookie = getCrsfCookie();
    
        var xhttp = new XMLHttpRequest();
    
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 503) {
                alert("Error when trying to toggle favourite!")
            }
        };
    
        url_arr = window.location.href.split("/")
        base_url = url_arr[0] + "//" + url_arr[2]
    
        var params = 'signal_id=' + signal_id;
        xhttp.open('POST', base_url + destination_url, true);
        xhttp.setRequestHeader('X-CSRFToken', csrfcookie);
        xhttp.send(params);
    }, 5000);
    

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 2020-06-13
      • 2020-07-04
      • 2019-12-11
      • 2019-12-19
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2011-06-22
      相关资源
      最近更新 更多