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

16,867

Solution 1

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.

Solution 2

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).

Solution 3

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> 
Share:
16,867
TIMEX
Author by

TIMEX

Updated on June 07, 2022

Comments