Ill try to explain it here but this is gonna require a video tutorial:

First there are several ways to achieve it. Although Anthony's suggestion 
(cache.ram) is optimal it didnt work on production, I dont know why 
cache.ram doesnt work on pythonanywhere.

I got the progress bar working on production using the scheduler, which i 
dont like cos its db intensive and more complex to setup, but i had no 
choice since the processes where too long to finish (10 minutes) and the 
http conection times out before its done.

Cache.ram
Create 2 controllers, one for your view and another one to get the progress.

def getprogress():
    return cache.ram('message', lambda: None, None)

def progress():
    # when a form is submitted, change progress each second
    if request.post_vars:
        n = 20 #simulate 20 iterations
        for i in range(n):
            msg = "Inserting records"
            percent = 100*(i+1) / n

            #update the percent each 5%
            if percent % 5 == 0:
                #store the array in ram [percent, text msg]
                message = cache.ram('message', lambda: ";".join([percent, 
msg]), time_expire=0)
                
            print "main:", percent, message
            sleep(1)
        #we are calling this controller through ajax so return a string 
when done
        return "done"
    else:
        message = cache.ram('message', lambda: -1, time_expire=0)
    return locals()

The view:
<div class="well">
        <div id="pbar">
            <div class="row">
                <div class="col-md-12">
                    <h3>Processing...</h3>
                </div>
                <div class="col-md-12">
                    <div class="progress progress-bar-xl" 
style="margin-top: 3px">
                        <div class="progress-bar progress-bar-warning" 
role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" 
style="width: 0%;">0%</div>
                    </div>
                </div>
            </div>
            <div class="row">
                <!-- <div class="col-md-1">
                    <input id="start" value="Pause" class="input-sm btn 
btn-primary btn-gradient btn-block dark" style="line-height: 0.8em;padding: 
0" type="submit">
                </div>
                <div class="col-md-1">
                    <input id="abort" value="Abort" class="input-sm btn 
btn-danger btn-gradient btn-block dark" style="line-height: 0.8em;padding: 
0" type="submit">
                </div> -->
            </div> 
        </div>
    </div>

js:
create a progress bar "class" jquery ui required if i recall.

<script type="text/javascript">

    function ProgressBar (selector) {
        var self = this;
        self.el = $(selector)
        self.text = self.el.find("h3");
        self.progress = self.el.find(".progress-bar");
        self.btnstart = self.el.find("#start");
        self.btnabort = self.el.find("#abort");
        
        self.value = 0;
        self.min = 0;
        self.max = 100;
        self.interval = 5000;
        self.running = false;
        self.timer = null;
        self.offset = 0;

        self.set_progress = function (value) {
            value = value || 0;
            var done = false;
            if (value>=self.max) {
                value = self.max
                done = true;
            };
            value = parseInt(value) + "%";
            self.progress.css("width", value);
            self.progress.text(value);
            if (done) self.done();
        };

        self.done = function (msg) {
            var msg = msg || "Process Completed"
            self.text.text(msg)
            console.log("done", self.timer);
            clearInterval(self.timer);
            self.running = false;
        };

        self.abort = function (e) {
            if (self.running) {

                self.value = 0;
                self.set_progress(0);
                self.text.text("Aborted");
                if (self.timer) {
                    clearInterval(self.timer);
                };
                self.running = false;
            };
        }

        #ask the server for the progress
        self.ask = function () {
            var ask = $.ajax({
                url: window.location.origin + "/default/getprogress"
                , type: "get"
            });

            ask.done(function (res, msg, xhr) {
                console.log(res);
                if (res=="-1") {
                    console.log("not running...?");
                    self.done();
                    return
                }
                // var data = res.split(";");

                var percent = parseInt(res[0]);
                var msg = res[1];
                // if (msg == "Error") {
                //    return self.done(msg);
                // };

                self.text.text(msg);
                // console.log("resp", res);
                self.value = percent + self.offset;
                if (percent == 80 && self.offset < 10) {
                    self.offset +=0.5;
                }
                if (percent == 80 && self.offset >= 10 && self.offset < 15) 
{
                    self.offset +=0.1;
                }
                self.set_progress(self.value);
            });

            ask.fail(function (xhr, status, error) {
                var resp = xhr.responseText;
                self.done("Error (see browser's console for details)");
                if (console) {
                    console.log(resp);
                };
                // console.log(resp);
                // console.log(status);
                // console.log(error);
                // clearInterval(self.timer);
                // self.running = false;

            })
        };

        self.start = function (e) {
            self.text.text("Processing...");
            if (!self.running) {
                console.log("running");
               
                self.value = 0;
                self.set_progress();
                self.ask();
                self.timer = setInterval(self.ask, self.interval);
                self.running = true
            } else {
                console.log("already runing");
            }
        }

        self.set_progress(self.value);
        // self.btnstart.on("click", self.start);
        // self.btnabort.on("click", self.abort);
    }

    var pbar = new ProgressBar("#pbar");
    pbar.start();

Note: this ProgressBar function is expecting a json response from the 
server with an array like [50, "Processing"]

The scheduler is more complex to setup i might need to do a video tutorial 
to exaplain it.

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to