Does Django have a way to open a HTTP long poll connection?
Asked Answered
R

4

19

Leave the connection open, until an event occurs.

Recoup answered 24/1, 2011 at 21:45 Comment(4)
poll? No idea what a long pole connection would be, though it sounds awesome. ;)Valles
What event would that be? Django is a web framework working with requests and responses, not a signalling protocol. Sorry if I misunderstand your question.Forbidden
Long polling is a method used for AJAX apps which should do something as soon as an event on the server occurs. So basically you start an AJAX request which isn't handled immediately but as soon as a certain event occurs. After getting a response the request is usually immediately restarted.Thief
@ThiefMaster. Yes, that's exactly what I want to do. How do I do that?Recoup
T
16

Have a look at Django / Comet (Push): Least of all evils? or The latest recommendation for Comet in Python? - COMET is another name for "ajax long-polling".

Apparently the most common approach is not doing it directly in django but with the help of an additional daemon (probably because e.g. Apache doesn't do well with lots of long-living connections). Nowadays nodejs+socketio is pretty popular for this (and it can even use WebSockets) - you just need to find a nice way to pass data between the two things. If it's unidirectional (e.g. just broadcasts to all connected clients) a redis pubsub queue is not a bad option for this.

But http://code.google.com/p/django-orbited/ is probably the most djangoish solution.

Thief answered 24/1, 2011 at 22:37 Comment(2)
Orbited is nice; but the next best thing is Server Sent Events; this post on html5rocks.com explains more and provides some code you can use.Laudatory
For a socket.io implementation in python: gevent-socketio.readthedocs.org/en/latestLaurilaurianne
H
9

For the future readers :)

I created a simple long polling django class views using Gevent, you can find it on github on https://github.com/tbarbugli/django_longpolling or get it from pypi (django_longpolling)

EDIT: I did some further experiment / deployment with django long polling / async workers and I can say that if possible opting to an external daemon is a very good choice, especially if you use the db (when using async worker you need a db connection pool or you are going to have the amount of worker connections bound to your db connection limits which is not desiderable).

Happily answered 13/1, 2013 at 13:37 Comment(0)
P
1

I think the best way to asynchronous communication with Django is have a node server listening in another port and use the api client of Socket.io. In this way, you aren't dependent of the support of the modules for django and is very simple: Node listening the request from client, convert this request in a post request and send to Django for the port which listen Django. Is the best way i think.

server.js

var http=require('http');
var server = http.createServer().listen(3000);
var io=require('socket.io').listen(server);
var querystring=require('querystring');

io.on('connection',function(socket){
   console.log('Connected to the client');
   socket.on('new comment',function(data){
      console.log('Web--->Node');
      var values=querystring.stringify(data);
      console.log(values);
      var options={
        hostname:'localhost',
        port:'8000',
        path:'/create-comment',
        method:'POST',
        headers:{
          'Content-Type':'application/x-www-form-urlencoded',
          'Content-Length':values.length
        }
      }
      var request=http.request(options, function(response){
        response.setEncoding('utf8');
        response.on('data',function(data){
          //Here return django
          console.log('Django-->Node');
          io.emit('return comment',data);
        });
      });

      request.write(values);
      request.end();
   });
});

views.py

def trysock(request):
    print 'In tryshok'
    comments=Comment.objects.all()
    dic = {
              'name': 'User',
              'form': CommentForm(),
              'comments': comments
          }

    return render(request,'index.html',dic)

@csrf_exempt
def create_comment(request):
    print 'Django<---Node'
    Comment.objects.create(
            user = request.POST['user'],
            comment = request.POST['comment']
        )

    response = JsonResponse({'user' : request.POST['user'], 'comment' : request.POST['comment']})
    print response.content
    return HttpResponse(response.content)

index.html

<div class='col-md-12'>
       <div class='col-md-6'>
         <form method='POST'>
         {% csrf_token %}
         {{form.comment}}
         <button id='boton'>Comentar</button>
         </form> 
       </div>

       <div id='comentarios' class='col-md-6'>
         {% for comment in comments %}
         <p>{{ comment.user }} - {{ comment.comment}}</p>
         {% endfor %}
       </div>
     </div>
    <!-- Fin Formulario comentarios -->

   </div>
    <script>
          var socket=io.connect('http://localhost:3000');
          console.log(socket);
          $('#boton').on('click',Comentar);
          function Comentar(e){
            console.log('Comentar(e)')
            e.preventDefault();
            var datos = {
              user:"baurin",
              comment : 'comentario de prueba'
            };
            socket.emit('nuevo comentario',datos);
            console.log('Enviando....: '+datos.user + '-' + datos.comment);
          }
          socket.on('devolviendo comentario', function(data){
              console.log('Recibiendo...');
              var dato = JSON.parse(data);
              $('#comentarios').prepend('<p>' + dato.user + '-' + dato.comment + '</p>')
          });
        </script> 
Prominence answered 27/7, 2015 at 11:28 Comment(0)
L
0

In 2022 the official django channels lets you handle long polling workloads.

Licentiate answered 25/8, 2022 at 8:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.