Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Leave the connection open, until an event occurs.

like image 915
TIMEX Avatar asked Jan 24 '11 21:01

TIMEX


People also ask

How does HTTP long polling work?

HTTP Long Polling is a technique used to push information to a client as soon as possible on the server. As a result, the server does not have to wait for the client to send a request. In Long Polling, the server does not close the connection once it receives a request from the client.

Does Django use HTTP?

Django uses request and response objects to pass state through the system. When a page is requested, Django creates an HttpRequest object that contains metadata about the request.

What is long polling Python?

What is long polling? Long polling is a technique used in web applications to enable a low-latency response to server messages without the CPU or traffic overhead of high frequency polling.


3 Answers

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.

like image 167
ThiefMaster Avatar answered Oct 20 '22 13:10

ThiefMaster


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

like image 30
Tommaso Barbugli Avatar answered Oct 20 '22 14:10

Tommaso Barbugli


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> 
like image 35
Baurin Leza Avatar answered Oct 20 '22 12:10

Baurin Leza