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.
Related
I am using a Django form to generate my HTML form.
I wanted to use the data from my form as an API payload.
if request.method == 'POST':
form = GetKeyForm(request.POST)
if form.is_valid():
appkey = form.cleaned_data['appkey']
secretkey = form.cleaned_data['secretkey']
shop_token = form.cleaned_data['shop_token']
shop_domain = form.cleaned_data['shop_domain']
payload = {
"account_platform": {
"shop_token": {shop_token},
"shop_secret": "",
"shop_domain": {shop_domain},
},
"utoken": {utoken}
}
headers = {
"Accept": "application/json",
"Content-Type": "application/json"
}
This is the error that I am getting:
Object of type set is not JSON serializable
I am trying to decrypt encrypted text and return the plain text through ajax call, instead of getting the message response I get an HTML page back as a response. I have tried returning the response as JSON but still getting the same HTML response.
function loadMessage() {
fetch("{% url 'chat:history' chatgroup.id %}")
.then( response => response.json() )
.then( data => {
for (let msg of data) {
var message=msg.message;
$.ajax({
type: 'GET',
url: '',
data: { message: message},
success: function(response){
broadcastMessage(response.message, msg.username, msg.date_created)
}
})
}
})
}
views.py
def get(request):
message = request.GET.get('message')
key = b'\xa8|Bc\xf8\xba\xac\xca\xdc/5U0\xe3\xd6f'
cipher = AES.new(key, AES.MODE_CTR)
nounce = b64encode(cipher.nonce).decode('utf-8')
if request.is_ajax():
nounce_ = self.nounce
msg_ = self.message
key = self.key
nounce = b64decode(nounce_)
ct = b64decode(msg_)
cipher = AES.new(key, AES.MODE_CTR, nounce=nounce)
msg_ = cipher.decrypt(ct)
mwssage = msg_.decode()
return JsonResponse({'message': message})
return render(request, 'chat/room.html')
The path to the decryption view was empty, after adding a path in the url it worked.
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
Django can only concatenate str (not "list") to str
Error Messages.......
I have some code like this:
function form_submit() {
var arr_category = new Array();
var arr_lawyer = new Array();
var data = new Object();
$('input[name^="category_idx"]').each(function() {
arr_category.push($(this).val());
});
$('input[name^="lawyer_idx"]').each(function() {
arr_lawyer.push($(this).val());
});
console.log("arr_category=="+arr_category);
console.log("arr_lawyer=="+arr_lawyer);
if (confirm('edit??') == true) {
data.arr_category = arr_category;
data.arr_lawyer = arr_lawyer;
call_ajax('/admin/lawyer/recommend_add', data);
//alert("arr_lawyer=="+arr_lawyer);
}
}
Am I doing well in jquery?
look at console.log
arr_category==1,2,3,4,5,6,7,8,9
arr_lawyer==64,37,57,58,130,62,38,51,110
admin_view.py
#csrf_exempt
def recommend_add(request):
print("TEST BANG VALUE------------")
if request.is_ajax() and request.method == "POST":
arr_category = request.GET.getlist('arr_category[]')
print("arr_category------------" + arr_category)
code = 0
msg = "TEST."
data = json.dumps({
'code': code,
'msg': msg,
#'retURL': retURL
})
return HttpResponse(data, content_type='application/json')
I want to print.
error message
TypeError: can only concatenate str (not "list") to str
How can I do that?
In case if you want to return a python interpreter error message to jquery's ajax call then you can use the below syntax.
def recommend_add(request):
print("TEST BANG VALUE------------")
if request.is_ajax() and request.method == "POST":
try:
arr_category = request.GET.getlist('arr_category[]')
print("arr_category------------" + arr_category)
code = 0
msg = "Success"
except Exception as e:
code = '' # anything you want as per your internal logic in case of error.
msg = str(e)
data = json.dumps({
'code': code,
'msg': msg,
#'retURL': retURL
})
return HttpResponse(data, content_type='application/json')
Please ignore my indentation.
in your print code try this
print("arr_category------------:", arr_category)
I am working on a python django web app in which I want to implement internationalization and auto translate the whole app into french or chinese.
I took reference from this site https://www.metod.io/en/blog/2015/05/05/django-i18n-part-1/
But whenever I try to run the app it shows this error:
500: ValueError at /en/get_dashboard_data/ The view
dashboard.views.getDashboardData didn't return an HttpResponse object.
It returned None instead.
And url get_dashboard_data is fetching data through ajax.
url(r'^get_dashboard_data/$', views.getDashboardData, name='getDashboardData'),
view
#login_required(login_url='/')
def getDashboardData(request):
dbname = request.user.username
if request.method == 'POST' and request.is_ajax():
if request.POST.get('action') == 'sale_chart_data':
data = DashboardData(dbname).getSaleChartData()
channel_list = data[0]
data_list = data[1]
print 123, data_list, channel_list
return HttpResponse(json.dumps({'channel_list':channel_list, 'data_list':data_list}), content_type='application/json')
if request.POST.get('action') == 'get_sale_numbers':
sale_data = DashboardData(dbname).getSaleNumbers()
return HttpResponse(json.dumps({'sale_number_data':sale_data}), content_type='application/json')
if request.POST.get('action') == 'get_inventory_numbers':
inventory_data = DashboardData(dbname).getInventoryData()
return HttpResponse(json.dumps({'inventory_data':inventory_data}), content_type='application/json')
if request.POST.get('action') == 'get_order_numbers':
order_data = DashboardData(dbname).getOrderData()
return HttpResponse(json.dumps({'order_data':order_data}), content_type='application/json')
if request.POST.get('action') == 'get_hourly_data':
order_data = DashboardData(dbname).getHourlyData()
sale_data = order_data[1]
count_data = order_data[0]
return HttpResponse(json.dumps({'sale_data':sale_data, 'count_data':count_data}), content_type='application/json')
if request.POST.get('action') == 'top_performers':
data = DashboardData(dbname).getTopPerformers()
inventory_count_dict = data[0]
current_month_dict = data[1]
last_month_dict = data[2]
current_quarter_dict = data[3]
current_year_dict = data[4]
channel_list = data[5]
return HttpResponse(json.dumps({'inventory_count_dict':inventory_count_dict,'current_month_dict':current_month_dict,'last_month_dict':last_month_dict,'current_quarter_dict':current_quarter_dict,'current_year_dict':current_year_dict,'channel_list':channel_list}), content_type='application/json')
if request.POST.get('action') == 'top_products':
product_data = DashboardData(dbname).getTopProducts()
return HttpResponse(json.dumps({'product_data':product_data}), content_type='application/json')
javascript
function getSaleChart(){
$.ajax({
url : "/get_dashboard_data/",
type : "POST",
data : {action:'sale_chart_data'},
success : function(response) {
channel_list = response.channel_list;
data_list = response.data_list;
c3.generate({
bindto: '#sale-chart-30-days',
data:{
x: 'dates',
xFormat: '%b %d',
columns: data_list,
colors:{
Flipkart: '#1AB394',
Paytm: '#BABABA'
},
type: 'bar',
groups: [ channel_list ]
},
axis: {
x: {
type: 'timeseries'
}
}
});
},
error : function(xhr,errmsg,err) {
toastr["error"]("Something Broke.", "Oops !!!.");
console.log(xhr.status + ": " + xhr.responseText);
}
});
}
This is why you should really practice more defensive programming. Though you insist that the request method is POST and it is ajax and the action is sale_chart_data one of the three isn't what you expect it to be.
Your function really should be like follows. It's plain old good practice.
def getDashboardData(request):
dbname = request.user.username
if request.method == 'POST' and request.is_ajax():
action = request.POST.get('action')
if action == 'sale_chart_data':
data = DashboardData(dbname).getSaleChartData()
....
...
# other if conditions here
else :
return HttpResponse(json.dumps({'message':'Unknown action {0}'.format(action)}), content_type='application/json')
else :
return HttpResponse(json.dumps({'message':'Only ajax post supported'}), content_type='application/json')
And then you ought to set break points and evaluate the request to figure out what exactly is happening in this particular request.
My guess would be that your JavaScript does indeed make a POST request to /get_dashboard_data/ but it receives a redirect response (HTTP 301 or 302) to /en/get_dashboard_data/ due to some kind of i18n middleware.
The browser follows the redirect, but the new request to /en/get_dashboard_data/ is a GET request.
Edit:
When following a redirect, the browser will always perform the second request as GET, there is no way to prevent that. You have several options to solve this:
make the initial request to the right application. This means you have to pass your i18n URL into your JavaScript instead of hardcoding it. You can add something like this to your template:
<script>var dashBoardDataUrl = "{% url "name-of-dashboard-url" %}"</script>
as your "actions" just get code, you could just accept a GET request and read the action from query paramters
Split that view into several smaller views that accept GET request so you have something that resembles a REST API.