Lelo Lelo - 5 months ago 21
HTML Question

Show "still loading" in django

I have two things I want to address, and I'm new to

django
and styling: First, I have this algorithm I'm running on the upload file and it takes time to load, so I want to show loading message or so until the
output.csv
is generated and ready to download (after home function is executed). I'm very new to styling and templating, can anyone help me on how to do that?

My files are like this:

view.py:

from __future__ import division
from django.shortcuts import render
from uploader.models import UploadForm,Upload
from uploader.models import Book
import io
from io import TextIOWrapper
import csv
from csv import DictReader
from io import StringIO
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
import csv
import logging
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.cluster import AgglomerativeClustering
import csv
from csv import DictReader
import numpy
from numpy.random import *
import numpy as np
import random
from functools import partial
from sklearn.metrics import pairwise_distances_argmin_min
from scipy.spatial.distance import pdist, squareform
import pandas as pd
import functools
from scipy import spatial
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from math import pi, acos
from sklearn.metrics.cluster import adjusted_rand_score
from sklearn.metrics import jaccard_similarity_score
import pprint
from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import Normalizer
from sklearn import metrics
from sklearn.cluster import KMeans, MiniBatchKMeans
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
from django.core.files.storage import default_storage
import codecs
from django.utils.encoding import smart_text
from django.http import HttpResponse
from django.conf import settings #or from my_project import settings
from django.http import StreamingHttpResponse
from wsgiref.util import FileWrapper
from django.utils.encoding import smart_str

def send_file(request):

filename = settings.MEDIA_ROOT +'/'+ 'output1.csv'
#filename= r"C:\Users\A6B0SZZ\PycharmProjects\sample\media\output1.csv"
download_name ="output1.csv"
wrapper = FileWrapper(open(filename))
response = HttpResponse(wrapper,content_type='text/csv')
response['Content-Disposition'] = "attachment; filename=%s"%download_name
return response



def home(request):
if request.method=="POST":
img = UploadForm(request.POST, request.FILES)
if img.is_valid():

# paramFile = request.FILES['pic']
paramFile =io.TextIOWrapper(request.FILES['pic'].file)
portfolio1 = csv.DictReader(paramFile)
print(type(paramFile))

users = [row["BASE_NAME"] for row in portfolio1]
print(len(users))

my_list = users
vectorizer = CountVectorizer()
dtm = vectorizer.fit_transform(my_list)

lsa = TruncatedSVD(n_components=100)
dtm_lsa = lsa.fit_transform(dtm)
dtm_lsa = Normalizer(copy=False).fit_transform(dtm_lsa)
similarity = np.asarray(numpy.asmatrix(dtm_lsa) * numpy.asmatrix(dtm_lsa).T)
k = len(my_list)
dist1 = (1- similarity)
# dist1=similarity
# dist1.astype(float)
#print(dist1)
# print(cosine_similarity(tfidf_matrix[3:4], tfidf_matrix))
# float dist = 1 - similarity;
data2 = np.asarray(dist1)
arr_3d = data2.reshape((1, k, k))
# arr_3d= 1- arr_3d
#print(arr_3d)

no_clus = 40
for i in range(len(arr_3d)):
# print (i+1910)
# km = AgglomerativeClustering(n_clusters=no_clus, linkage='ward').fit(arr_3d[i])
km = AgglomerativeClustering(n_clusters=no_clus, linkage='average').fit(arr_3d[i])
# km = AgglomerativeClustering(n_clusters=no_clus, linkage='complete').fit(arr_3d[i])
# km = MeanShift()
# km = KMeans(n_clusters=no_clus, init='k-means++')
# km = MeanShift()
# km = km.fit(arr_3d[i])
# print km
labels = km.labels_

csvfile = settings.MEDIA_ROOT +'\\'+ 'images\\export.csv'

csv_input = pd.read_csv(csvfile, encoding='latin-1')
csv_input['cluster_ID'] = labels
csv_input['BASE_NAME'] = my_list
csv_input.to_csv(settings.MEDIA_ROOT +'/'+ 'output.csv', index=False)
clus_groups = list()
for j in range(no_clus):
# print(" cluster no %i:%s" % (j, [my_list[i] for i, x in enumerate(labels) if x == j]))
list_of_ints = ([my_list[i] for i, x in enumerate(labels) if x == j])
clus_groups.append(' '.join(list_of_ints))
vectorizer = CountVectorizer()
dtm = vectorizer.fit_transform(my_list)

lsa = TruncatedSVD(n_components=100)
dtm_lsa = lsa.fit_transform(dtm)
dtm_lsa = Normalizer(copy=False).fit_transform(dtm_lsa)
similarity = np.asarray(numpy.asmatrix(dtm_lsa) * numpy.asmatrix(dtm_lsa).T)
k = len(my_list)
dist1 = 1 - similarity

data2 = np.asarray(dist1)
arr_3d = data2.reshape((1, k, k))
# arr_3d= 1- arr_3d


###########################################here#######################
no_clus = 5
for i in range(len(arr_3d)):

km = KMeans(n_clusters=no_clus, init='k-means++')
km = km.fit(arr_3d[i])

labels2 = km.labels_

print(labels2)

labels = labels.tolist()
labels2 = labels2.tolist()
# new=list()


csv_input = pd.read_csv(settings.MEDIA_ROOT +'/'+ 'output.csv',encoding='latin-1')
labels1 = csv_input['cluster_ID']
new_list = []
for k in labels1:
new_list.append(labels2[k]) # lookup the value in list2 at the index given by list1

print(new_list)
print(len(new_list))
csv_input = pd.read_csv(settings.MEDIA_ROOT +'/'+ 'output.csv',encoding='latin-1')
csv_input['cluster_ID'] = labels
csv_input['BASE_NAME'] = my_list
csv_input['User_Map'] = new_list
csv_input.to_csv(settings.MEDIA_ROOT + '/' + 'output1.csv', index=False)
filename= settings.MEDIA_ROOT +'/'+ 'output.csv'
send_file(request)
# my_list = portfolio
#save_file('output1.csv')
# csv(request)
# return HttpResponseRedirect(reverse('labels'))
return render(request, 'home.html', {'labels': labels})
else:
img=UploadForm()
images=Upload.objects.all()
return render(request,'home.html',{'form':img,'images':images})


My
home.html
:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="padding:40px;margin:40px;border:1px solid #ccc">
<h1>Upload the CSV File to Run the Algorithm on:</h1>
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %} {{form}}
<input type="submit" value="Upload" />

</form>

<a href="/media/output1.csv">Download CSV File</a>

</div>
</body>
</html>




url.py:

from django.conf.urls import url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from uploader import views


urlpatterns = [
url(r'^upload/$', 'uploader.views.home', name='labels'),
url(r'^media/output1.csv', 'uploader.views.send_file'),
url(r'^admin/', admin.site.urls),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


I'm assuming I need to add staff to my html file, or to the template dir in general. I appreciate the help.
The second thing is that I need a box so that the user will determine how many clusters for the input, right now I defined it as 5, right before when I mentioned "#####here#####".. How can I do that? I appreciate the help with the code.

One more
thing,how I can make the link of
download csv file
show up only when the
home
function is executed?

Edit:
I tried to develop the number input box, which it should be as
get.request
I think:

My form.py

from django import forms

class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)


View.py

from .forms import NameForm


def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'GET':
# create a form instance and populate it with data from the request:
form = NameForm(request.GET)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return render_to_response('new.html')

# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()

return render(request, 'new.html', {'form': form})


Later in
view.py
, inside
home function
:

no_clus=get_name(request)
for i in range(len(arr_3d)):

km = KMeans(n_clusters=no_clus, init='k-means++')
km = km.fit(arr_3d[i])

labels2 = km.labels_
# error = km.inertia_
print(labels2)



new.html

<form method="get">
<label for="your_name">Number of Users: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" style="display:none;">
</form>


Error:
unorderable types: int() < HttpResponse()

Edit:


Want optional input box, if user won't input anything, the default function after the else should execute, I tried the following but didn't work:

view.py:

def number_cluster(request, data_size):
if request.method == 'GET':
img1 = Book(request.GET)
if img1.is_valid():
no_cluster = int(request.POST.get('num_clusters1'))
return render(int(no_cluster), {'form': img1})
else:
no_cluster = data_size / 2.34
return (int(no_cluster))


Models:

class Book(models.Model):
description = models.TextField(blank=True)


**`New.html`**


Optional : Please insert Number of Clusters

Answer

Not the final solution - but to give an idea: As Rajesh did mention in the comment this can be addressed client side (with JavaScript/jQuery). So you could add the desired message when submitting the form.

Question 1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
    <style>
        #loading {
            background: red;
            position: fixed;
            top: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
<div style="padding:40px;margin:40px;border:1px solid #ccc">
    <h1>Upload the CSV File to Run the Algorithm on:</h1>
    <form action="#" method="post" enctype="multipart/form-data">
        {% csrf_token %} {{form}}
         <input type="submit" value="Upload" />

    </form>

<a href="/media/output1.csv">Download CSV File</a>

</div>

<script>
    $(function(){
        $('form').on('submit', function(e){
            $('body').append('<div id="loading">Loading...</div>')
        });
    })
</script>

</body>
</html>

Question 2

In your template:

<!-- template.html -->
<form ...>
    ...
    <input type="number" name="num_clusters" min="1" max="500">
    ...

In your view:

# view.py
def home(request):
    if request.method=="POST":
        num_clusters = request.POST.get('num_clusters', 10) # 10 as default