How to Post csv file in simple Html into Django api? - django

I tried post FormData using "angular Js" and then using Directly post html to django api But It Will be failure , Anyone Tried it and Known It Please Tell me your answer it is the full code i tried out :
html:
<form action="http://localhost:55555/collaboratoradmin/test/upload_driver" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="csv_file" accept=".csv"
onchange="angular.element(this).scope().getFileDetails(this)" />
<button type="submit" ng-click="uploadFiles()">upload</button>
Angular Js:
$scope.getFileDetails = function (e) {
$scope.files = [];
$scope.$apply(function () {
var file = e.files[0];
filename = '';
if ('name' in file)
filename = file.name;
else
filename = file.fileName;
});
};
$scope.uploadFiles = function () {
//FILL FormData WITH FILE DETAILS.
// ADD LISTENERS.
var objXhr = new XMLHttpRequest();
objXhr.addEventListener("progress", updateProgress, false);
objXhr.addEventListener("load", transferComplete, false);
// SEND FILE DETAILS TO THE API.
objXhr.open('POST', endpoint + '/collaboratoradmin/test/upload_driver', true);
var fd = new FormData();
fd.append("filename", filename);
fd.append("csv_file", file);
objXhr.send(fd);
}
// UPDATE PROGRESS BAR.
function updateProgress(e) {
if (e.lengthComputable) {
document.getElementById('pro').setAttribute('value', e.loaded);
document.getElementById('pro').setAttribute('max', e.total);
}
}
// CONFIRMATION.
function transferComplete(e) {
alert("Files uploaded successfully.");
}
Django api:
#api_view(['POST'])
def upload_driver(request):
if request.POST and request.FILES:
csvfile = request.FILES['csv_file']
dialect = csv.Sniffer().sniff(codecs.EncodedFile(csvfile, "utf-8").read(1024))
csvfile.open()
reader = csv.reader(codecs.EncodedFile(csvfile, "utf-8"), delimiter=',', dialect=dialect)
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myproject.myapp.views.list'))
print(list1)

Related

Django : Binary File Download on Button click returning incorrect data

Implemented file download on button click for a binary file using Ajax and Django as below
Django Code
def generate(self,parms):
#pdb.set_trace()
json_data = json.loads(parms.body.decode('utf-8'))
d_fldr = BASE_DIR+'/tmp/'+json_data['sessn']+'/'
resp = None
try:
data = None
with open(d_fldr + json_data['fn'],'rb') as f:
data = f.read()
resp = HttpResponse(data,'application/octet-stream')
resp['Content-Disposition'] = 'attachment;filename=%s'%(json_data['fn'])
except:
resp = None
return resp
AJAX Call on Button Click
function ajax_file_send(req,onSucc,onFail) {
req['beforeSend'] = function() {
$('#loading').modal({backdrop: "static"});
}
req['complete'] = function(){
$('#loading').modal('hide')
}
req['error'] = onFail;
req['success'] = onSucc;
$.ajax( req );
}
....
.....
$('#btn_gen').on('click',function(e) {
console.log("Generate clicked");
json = { 'sessn' : global_sessn,
'fn' : $('#kdb_sel').val(),
'xml' : $('#kdb_xml').val()
};
var req = {
url: "ajx_generate",
method: "post",
processData: false,
contentType: false,
headers: { "X-CSRFToken": '{{ csrf_token }}'
},
data: JSON.stringify(json),
//responseType: 'arraybuffer',
};
ajax_file_send(req,fun_succ1,fun_fail1);
function fun_succ1(response) { // on success..
console.log("fun_succ1 success");
var binaryData = []; binaryData.push(response);
var a = document.createElement('a');
var url = (window.URL || window.webkitURL).createObjectURL(new Blob(binaryData, {type: "application/kdb"}));
a.href = url;
a.download = $('#kdb_sel').val();
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
Issue
The file that gets downloaded(2KB) on button click, is more in size than that is originally on server (1.4Kb) , while on Network TAB in DEV Tools Header : Content-Length is correctly set to 1.4Kb

Pass javascript variable to views.py

I really need some help on this subject, which seems easy, but i cant get myself to figure out the problem.
I understand that using ajax is the best way to pass a variable from a template to a view.
Is what i have done good, or would you recommend i try something different ?
function updateArea(e) {
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if (data.features.length > 0) {
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area*100)/100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','data.geojson');
} else {
answer.innerHTML = '';
if (e.type !== 'draw.delete') alert("Use the draw tools to draw a polygon!");
}
}
I want to take the area variable and convertedData variable and pass them to a view.
So after some searching and trial and error, here is what I tried to do using Ajax.
When I run this i get no errors, but i get nothing in my database.
template.html
<form id="areaform" method="POST">
{% csrf_token %}
<input type="submit" name="area" value=""/>
</form>
$(document).on('submit', '#areaform',function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url:'fertisatmap/area',
data:{
name: $('#area').val(),
},
sucess:function(){}
});
});
urls.py
path('fertisatmap/area', fertisat_views.fertisatareaview, name='fertisat-area'),
views.py
def fertisatareaview(request):
if request.method == "POST":
area = request.POST['area']
Fertidb.objects.create(
area = area)
return HttpResponse('')

Django2: Submit and store blobs as image files

I have made a few Django projects after having read the tutorial but I am by no means an expert in Django.
I am trying to take a screenshot of the current page and store it (if one does not exist).
To achieve this, we require a few things:
function to get screen shot of current page
function to async post this image to a view which should store it
view that stores the posted image
However, the screen shot function results in a Blob and I am having trouble getting a Django view to properly handle this.
A demo project is available here: https://gitlab.com/SumNeuron/so_save_blob
Function for screenshot
const screenshot = (function() {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype
|| nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function (el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function (e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function capturePage(){
urlsToAbsolute(document.images);
urlsToAbsolute(document.querySelectorAll("link[rel='stylesheet']"));
var screenshot = document.documentElement.cloneNode(true);
var b = document.createElement('base');
b.href = document.location.protocol + '//' + location.host;
var head = screenshot.querySelector('head');
head.insertBefore(b, head.firstChild);
screenshot.style.pointerEvents = 'none';
screenshot.style.overflow = 'hidden';
screenshot.style.webkitUserSelect = 'none';
screenshot.style.mozUserSelect = 'none';
screenshot.style.msUserSelect = 'none';
screenshot.style.oUserSelect = 'none';
screenshot.style.userSelect = 'none';
screenshot.dataset.scrollX = window.scrollX;
screenshot.dataset.scrollY = window.scrollY;
var script = document.createElement('script');
script.textContent = '(' + addOnPageLoad_.toString() + ')();';
screenshot.querySelector('body').appendChild(script);
var blob = new Blob([screenshot.outerHTML], {
type: 'text/html'
});
return blob;
}
return capturePage
})()
Function to async post Blob
function setupAjaxWithCSRFToken() {
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// set csrf header
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}
function asyncSubmitBlob( url, blob ) {
var fd = new FormData();
fd.append('image', blob);
$.ajax({
url: url,
type: "POST",
data: fd,
contentType: false,
processData: false,
success: function(response){ console.log(response) },
error: function(data){ console.log(data) }
})
}
So to submit a screenshot of the current page:
setupAjaxWithCSRFToken()
const page = window.location.pathname;
const blob_url = "{% url 'my-app:post_blob' 'REPLACE' %}".replace(/REPLACE/,page == '/' ? '' : page)
asyncSubmitBlob( blob_url, screenshot() )
View to store the posted blob image
urls.py
...
from django.urls import include, path
...
app_name='my-app'
url_patterns=[
...
path('post_blob/', views.post_blob, {'page':'/'},name='post_blob'),
path('post_blob/<page>', views.post_blob,name='post_blob'),
...
]
views.py
from .models import PageBlob
...
def post_blob(request, page):
if request.FILES: # save screenshot of specified page
try:
pb = PageBlob.objects.all().filter(page=page))
if not pb.count():
pb = PageBlob()
pb.page = page
pb.blob = request.FILES['image']
pb.save()
return HttpResponse('Blob Submitted')
except:
return HttpResponse('[App::my-app]\tError when requesting page_image({page})'.format(page=page))
else: # return screenshot of requested page
try:
# get objects storing screenshot for requested page
pb = PageBlob.objects.all().filter(page=page)
# if one exists
if pb.count():
pb = pb[0]
## this just returns the string literal "blob"
return HttpResponse(str(pb.blob))
return HttpResponse('[App::my-app]\tNo blob for {page}'.format(page=page))
except:
return HttpResponse('[App::my-app]\tError when trying to retrieve blob for {page}'.format(page=page))
return HttpResponse('Another response')
models.py
class PageBlob(models.Model):
page = models.CharField(max_length=500)
blob = models.TextField(db_column='data', blank=True)
But I can not seem to faithfully capture and retrieve the blob.
Many S.O. questions of storing blobs use the model approach with import base64 to encode and decode the blob. One even recommends using the BinaryField. However, Django's documentation states firmly that BinaryField is not a replacement for the handling of static files.
So how could I achieve this?
S.O. posts I have found helpful to get this far
Upload an image blob from Ajax to Django
How to screenshot website in JavaScript client-side / how Google did it? (no need to access HDD)
How to download data in a blob field from database in django?
passing blob parameter to django
Returning binary data with django HttpResponse
https://djangosnippets.org/snippets/1597/
Django Binary or BLOB model field
Django CSRF check failing with an Ajax POST request
How can javascript upload a blob?

Unable to get request.FILES django

I am trying to upload a text file to my django backend, but my request.FILES is always empty.
I am using axios to send the file and have followed the django requirement to have 'multipart/form-data' as content type of the request.
What am I missing?
On my app.js I send a post request via:
new Vue({
el: '#app',
data: {
reqtype: '',
uploadedFile: '',
},
methods: {
onSubmit(event) {
this.submitLoading = true;
if (! this.validateForm(this)) {
event.preventDefault();
this.submitLoading = false;
return;
}
var formData = new FormData();
formData.append("reqtype", this.reqtype)
formData.append('fileToUpload', this.uploadedFile)
axios.post('/sreqtool/tc/', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
},
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
var reader = new FileReader();
var vm = this;
reader.onload = (e) => {
vm.uploadedFile = e.target.result;
};
reader.readAsDataURL(files[0]);
}
},
}
On the network request payload:
------WebKitFormBoundarymAnl54hGVTifZzwM Content-Disposition: form-data; name="reqtype"
filebased
------WebKitFormBoundarymAnl54hGVTifZzwM Content-Disposition: form-data; name="fileToUpload"
data:text/plain;base64,OTA1NTIzMzg2NQ0KOTE3NTAwMTU0Mg0KOTc3NDczNjcyNg0KMTIzNTQ2ODQ1Ng==
------WebKitFormBoundarymAnl54hGVTifZzwM--
In my views.py I have:
#csrf_exempt
def index(request):
if request.method == 'POST':
DLOG.info(request.POST)
DLOG.info(request.FILES)
form = ExtractForm(request.POST, request.FILES)
if form.is_valid():
res = QueryManager.processRequest(request.user, form.cleaned_data)
DLOG is my logger and the output of the dlog is:
[2017-12-18 16:51:06,510] INFO views index: <QueryDict: {u'fileToUpload': [u'data:text/plain;base64,OTA1NTIzMzg2NQ0KOTE3NTAwMTU0Mg0KOTc3NDczNjcyNg0KMT
IzNTQ2ODQ1Ng=='], u'reqtype': [u'filebased']}>
[2017-12-18 16:51:06,512] INFO views index: <MultiValueDict: {}>
it says your image encoded to base64
{u'fileToUpload': [u'data:text/plain;base64,OTA1NTIzMzg2NQ0KOTE3NTAwMT...
I am able to read the file content now.
I used the link from Farrukh's comment a
stackoverflow answer
Code is updated to:
#csrf_exempt
def index(request):
if request.method == 'POST':
form = ExtractForm(request.POST, request.FILES)
if form.is_valid():
res = QueryManager.processRequest(request.user, form.cleaned_data)
format, imgstr = data.split(';base64,')
ext = format.split('/')[-1]
data = ContentFile(base64.b64decode(imgstr), name='temp.' + ext)
filetext = data.read()
filetext contains the string I need from the file.

How to pass django ajax data to template?

I'm trying to pass a 2d array into a template via ajax. I managed to get the data from the server on click, but I don't know how I can handle that data inside a template. For instance, if I put the returned 'data' into a div then it just lists the first column. How to access specific data with, for instance:
{% for printers in printer_list %}
{{ printer.email }}
{% endfor %}
Javascript:
$(".printersToggle").click(function() {
$.get("/ajax", function(data) {
/* What goes here? */
});
});
views.py:
def ajax_test(request):
if request.is_ajax():
printer_list = User.objects.all()
else:
printer_list = "Not ajax"
return HttpResponse(printer_list)
# Am I doing this bit right?
urls.py:
url(r'^ajax$','website.views.ajax_test'),
Views.py
Below we are receiving an AJAX POST and filtering an object based on 'VarID', and building a list of dictionaries that each contain an OptionID, OptionValue, and OptionLabel value. Finally, you should convert whatever list or dict or combo that you want in json.
def currentoptions(request):
if request.is_ajax():
currentOptions = Option.objects.filter(VariableID=int(request.POST['VarID']))
response = []
for i in currentOptions:
vallabel = {}
vallabel['OptionID'] = i.id
vallabel['OptionValue'] = i.Value
vallabel['OptionLabel'] = i.Label
response.append(vallabel)
json = simplejson.dumps(response)
return HttpResponse(json, mimetype="text/json")
else:
pass
Javascript needed for CSRF reasons.
<script type="text/javascript">
jQuery(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
</script>
Javascript for your specific AJAX request.
To display the values from the dicts in the lists we are iterating through the returned data on success of the AJAX request. The JS functions are done with jQuery.
function AddOptions(VarID){
$.ajax({
type:"POST",
url:"{% url builder.views.currentoptions %}",
data: {VarID: VarID},
success: function(data){
$('#OptionTable > tbody > tr').remove();
$.each(data, function(index) {
$('#OptionTable > tbody:last').append('<tr id=Option_'+data[index].OptionID+'><td>'+data[index].OptionValue+'</td><td>'+data[index].OptionLabel+'</td><td><i class="icon icon-remove"></i>');
});
}
});
}
This has to be done using javascript. Once the template is generated on the server and the page is displayed in the visitors web browser it is nothing more than HTML with JavaScript. In order to manipulate the page you need to use JavaScript.