2
#In my views.py file
pi1 = None
pis1 = None
def my_func():
    #Essentially this function sets a random integer to pi1 and pis1
    global pi1, pis1
    pi1 = randint(0,9)
    pis1 = randint(0,9)
    return        

def index(request):

    my_func()

    context = {
        "pi1" : pi1,
        "pis1" : pis1,
    }

    return render(request, "index.html", context)

#In the index.html file
<h1>{{ pi1 }}</h1>
<h1>{{ pis1 }}</h1>

I've removed a lot of my code for simplicity, but this is the gist of it. Despite the code that I've posted for my_func, it is a time consuming function that causes index.html to load for awhile when it is accessed. How would I run my_func in the backround using celery and redis so that index.html loads more quickly?

I've read the celery documentation, but I am still having trouble setting up celery and redis. Thank you.

PiccolMan
  • 4,854
  • 12
  • 35
  • 53

2 Answers2

2

As is said previous, you might not need celery. Here's an example derived from case 2 of this: https://zapier.com/blog/async-celery-example-why-and-how/. It's fully working for me:

from time import sleep
import json
from django.http import HttpResponse
from django.shortcuts import render

def main_view(request):
    return render(request, 'index.html')

def ajax_view(request):
    sleep(10) #This is whatever work you need
    pi1 = "This is pi1" #I just made pi1/pis1 random values
    pis1 = "This is pis1"
    context = {
        "pi1" : pi1,
        "pis1" : pis1,
    }
    data = json.dumps(context)

    return HttpResponse(data, content_type='application/json')

My index.html contains:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Main View</title>
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
    <script>
    $(document).ready(function(){
        $.ajax({
            url: "/test_ajax/",
        }).done(function( data) {
            $("#pi1").text(data.pi1);
            $("#pis1").text(data.pis1); 
        });
    });
</script>
  </head>
  <body>
      <h1 id = "pi1">Loading</h1>
      <h1 id = "pis1">Loading</h1>
  </body>
</html>

And my urls.py contains:

from django.conf.urls import include, url
from django.contrib import admin
from testDjango.test import main_view, ajax_view

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^test/', main_view),
    url(r'^test_ajax/', ajax_view)
]

What happens when I visit localhost:8000/test/ is that I instantly see:

Initial visit

After about 10 seconds, I then see:

Image after 10 seconds

The idea is that you return your page instantly and use jquery to fetch the result of the operation whenever that's finished and update your page accordingly. You can add more things like progress bars/loading image etc. For your example, you can do the processing for pi1 and pis in the background and load it into the HTML after that's finished.

Ringil
  • 6,277
  • 2
  • 23
  • 37
  • Thanks for the idea, but can you please explain the javascript part? I don't understand what you are doing there. – PiccolMan Aug 21 '15 at 01:56
  • Also, after reading the page you linked I am under the impression that this is not going to load my page faster, but it is going to just allow me to add a loading bar to the page. – PiccolMan Aug 21 '15 at 02:15
  • Let's put some numbers to this. If your `pi1` and `pis1` take like 10 seconds to calculate. You have to spend 10 seconds calculating that at some point. You can't really avoid this unless you have a cached value already. From the link I showed, if you don't use any async things, the user has to wait this 10 seconds upfront. They have to deal with waiting 10 seconds while they see a blank page. What async does is that it lets you display something and gives back control of the page to the user while they wait the 10 seconds. It means no more blank pages, which makes it much nicer. – Ringil Aug 21 '15 at 09:57
  • Celery won't let you avoid waiting those 10 seconds any more than using stuff like this does. The benefits of celery come from when you need to do a lot of jobs. If you just need a single thing occassionally, it's really not needed. Regardless, what the javascript does in my example is is that when the page is loaded, it uses AJAX to send a request to get the info for `pis` and pi1s` and then it fills the

    s with the value of `pi1` and `pis1` after you take the 10 seconds of calculation. That way the user will get the information they want without looking at a blank screen the whole time.

    – Ringil Aug 21 '15 at 10:10
  • Thanks for the explanation. I still quite don't understand the javascript, but that's not your fault. If you know a good source that explains this Json javascript thing can you link it somewhere. Thanks. – PiccolMan Aug 22 '15 at 18:48
  • 1
    JSON is a format for data. It's not specific to javascript. I put it into JSON, because it's reasonably easy to read and is portable. jQuery is a convenient javascript package. It has a function called `.ajax`, which is what I've used. You can read about the basic idea of what ajax is here: https://learn.jquery.com/ajax/ – Ringil Aug 22 '15 at 18:53
0

You don't need celery here. You can load these values on page with AJAX request. You should create a separate view that will calculate this values and after the index.html is loaded call it with javascript.

svfat
  • 3,273
  • 1
  • 15
  • 34