0

I have a Django app, with a page in Admin where I can upload a zip file of product data, which then goes to get processed. I have the list status_message set up in Python so that it is constantly updated with information about how the processing is going.

While on Firefox, making this on my dev environment, this worked pretty well. When I tested it on Chrome the report was no longer displayed at all. More importantly, but perhaps related, is that when I push to my staging server and test it, as soon as the upload happens and the file begins to be processed, I get redirected to a 404 error page, and I don't know why. The biggest difference I can think of is SSL on the staging server, but not my dev environment. Finally, probably due to my inexperience with AJAX + Django, there is a final page refresh after the status message is loaded. That's annoying, but doing no real harm (unless it's also causing one of the other problems). My head's spinning. What's going on? Is one line the problem, my view, or the whole thing?

Problem 1. The report in the div #status-message updates as it comes in Firefox, but not Chrome.

EDIT 1: Turns out this partially comes from Chrome 28 caching things. See Jquery ajax random error in Chrome only. Now with this, Chrome displays the message after all processing, but still not as the status-message changes until then:

function retrieve_status()
{
  $.ajax({
    url: "print_status",
    success: function(data){
      $('#status-message').html("");
      for (var i=0; i<data['message'].length; i++)
        $('#status-message').append(data['message'][i] + "<br>");
        $('#status-message').scrollTop($('#status-message')[0].scrollHeight);
    },
    cache: false
  });
}

Problem 2. 404 error after zip upload only on staging server.

Edit 2: In the browser console from the staging server, I get the warning "The page at https://myapp.com/admin/product-load/ displayed insecure content from http://myapp.com/admin/product-load/print_status/?_=1380231818430." I haven't figured out how to fix this yet. The whole site is supposed to use SSL, and if you copy in that second path, it even forwards to the https version. The url: in the AJAX doesn't seem to matter. I even completely hardcoded the url with an https prefix and it said the same thing: url: https://myapp.com/admin/product-load/print_status",

Problem 3. Annoying page refresh after processing is complete.

Here's my code. I didn't trim much off because I'm not sure what is or isn't relevant.

views.py:

from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.admin.views.decorators import staff_member_required
from myappload.forms import ProductLoadForm
from myappload.load import ProductLoader
import json

status_message = []

@staff_member_required
def index(request):
    global status_message
    status_message = []
    if request.method == 'POST':
        form = ProductLoadForm( request.POST, request.FILES)
        if form.is_valid():
            product_data = request.FILES.get('file')
            loader = ProductLoader( zip_filename=product_data, index=False, status=record_status)
            load_report = loader.load()
            return render ( request, 'myappload/index.html', { 'form': form})
    else:
        form = ProductLoadForm()
    return render ( request, 'myappload/index.html', { 'form': form})

def record_status(status):
    global status_message
    status_message.append(status)
    print status

def print_status(request):
    return HttpResponse(json.dumps({ 'message': status_message }), content_type="application/json")

urls.py

from django.conf.urls.defaults import patterns, url

#  URLs
urlpatterns = patterns('myappload.views',
    url(r'^$', 'index', name='product_load_page'),
    url(r'^print_status/$', 'print_status', name='product_upload_status'),
)

forms.py

from django import forms

class ProductLoadForm(forms.Form):
    file = forms.FileField()

index.html:

{% extends "admin/base_site.html" %}

{% block content %}
<form name="product_load_form" class="form form-horizontal"
enctype="multipart/form-data" method="post">
  {% csrf_token %}
  {% include 'forms/basic.html' %}
  <input id="upload-button" type="submit" value="Upload"/>
</form>
<div id="status-message">
The status message will show up here <br>
</div>

<script>
function retrieve_status()
{
  $.get("print_status", function( data ) {
    $('#status-message').html("");
    for (var i=0; i<data['message'].length; i++)
      $('#status-message').append(data['message'][i] + "<br>");
      $('#status-message').scrollTop($('#status-message')[0].scrollHeight);
  });
}

$(document).ready(function() {
  retrieve_status();  //the page will refresh when done, calling this on load
  $('#upload-button').click(function() {
    setInterval(function(){retrieve_status()},500);
  });
  $('#status-message').css('height', $(window).height() - 170);
});
</script>
{% endblock %}
Community
  • 1
  • 1
nixjdm
  • 99
  • 1
  • 10
  • Couple of things - where's your forms action? Is there a reason you've put your JQuery function *outside* your ready() function? – professorDante Sep 26 '13 at 01:50
  • I'm not sure what you mean by the first question. The file upload is handled by an html form submit, with method=POST so that in the view.py it is captured by `def index(request)` which has an if block to handle the POST. The jquery function is called from inside `ready()`, I just put it outside because I thought it looked cleaner. I am thinking that using this method is causing the page refresh, and switching to using AJAX somehow to upload would be better. – nixjdm Sep 26 '13 at 19:34
  • Ah my apologies, you've bound the click event. Your get function is using AJAX already, though you probably know that. I'd say you're re-inventing the wheel a little - maybe look at the JQuery progressbar, with an AJAX callback to a url to answer the progress. Look at https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#upload-handlers – professorDante Sep 26 '13 at 20:02

0 Answers0