Storing JSON variable in django database - json

In my app that uses Gridster I am changing the widget positions and then saving it as a json variable.I want to store this json variable in django database.
For that I am not understanding how should I define a function in views.py and a class in models.py which can store the json variable
My HTML/JS template is
var URL = "{% url 'my_view_url' %}";
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
});
My views.py
def save_grid(request):
if request.method == 'POST':
# Some code to get json variable and store it to model
return HttpResponse('success') # if everything is OK
I want to write some kind of class in models.py corresponding to view.py so that JSON variable can be saved
Edit1
My models.py is
from django.db import models
from django.utils import timezone
from django.utils import simplejson as json
class update_grid(models.Model):
data = JSONField(null=True, blank=True)
I just want to send data from views to this model(If it is correct)
Edit 2
My JS Script is updated as follows
var URL = "{% url 'save-grid' %}";
$('.js-seralize-update').on('click', function () {
var s = gridster.serialize();
updated_grid=JSON.stringify(s);
$('#log').val(updated_grid);
function updategridster(updated_grid){
var data = updated_grid;
$.post(URL, data, function(response){
if(response === 'success'){ alert('Yay!'); }
else{ alert('Error! :('); }
});
}
updategridster(updated_grid);
});
Now I get this error
POST http://localhost:8000/calendar_grid/save-grid net::ERR_CONNECTION_ABORTED jquery.min.js:2

You have the built in JSONField if you use PostgreSQL.
Otherwise there are several implementations like django-jsonfield, for admin i pair this with django-jsoneditor
Then you can save the JSON data in a single field, and in the case of the built in, you can even do queries/filter on specific keys inside the JSON structure.

Related

How to send a file object from Flask API to Angular Frontend without storing it on the file system

I am trying send a file object of type BytesIO from flask API to angular frontend.
I am using json.dumps(). File object shouldn't be stored on file system. I am using memory for storing file object. Using io.BytesIO().
return json.dumps({'UserId': username, 'file': file_object}), 201
Typerror: <_io.BytesIO object> is not json searializable
You can use send_file with a file like object:
import io
from flask import send_file
#app.route("/send_file")
def send_file():
file = io.BytesIO()
file.write(b"Hello, World!")
file.seek(0)
return send_file(file, attachment_filename=f"example.txt", as_attachment=True)
And then I expect you'll do something with it in Javascript:
fetch('https://example.com/send_file')
.then(res => res.blob())
.then(blob => {
// Do something
});
http://blog.luisrei.com/articles/flaskrest.html
Please check this link and refer "RESPONSES" subtitle.
from flask import Response
#app.route('/hello', methods = ['GET'])
def api_hello():
data = {
'hello' : 'world',
'number' : 3
}
js = json.dumps(data)
resp = Response(js, status=200, mimetype='application/json')
resp.headers['Link'] = 'http://luisrei.com'
return resp

Why doesn't django redirect to new url using drag-and-drop file upload?

I want to incorporate a drag-and-drop to upload files using Django and HTML. I am able to upload the file and save it to the model "Document". After that, I want to be redirected to 'user:datapreparation', which will display the dataframe in a new page. However, I am not redirected and I stay on the same page ("user:userform").
Do you perhaps know why I am not redirected to datapreparation'?
Hereby the code.
Thank you for your help!
View:
class FileUploadView(View):
form_class = DocumentForm
template_name = 'user/model_form_upload.html'
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
document_name = str(request.FILES['file'])
if request.FILES['file'].size < 31457280: # max 30 mbs allowed
form = self.form_class(request.POST, request.FILES)
document_type = str(document_name.rsplit(".", 1)[1])
valid_document_types = ["txt", "csv", "xlsx"]
if document_type in valid_document_types:
a = Document.objects.all()[0]
a.file = request.FILES['file']
a.description = document_name
a.save()
return redirect('user:datapreparation')
Models:
class Document(models.Model):
description = models.CharField(max_length=255,blank=True)
file = models.FileField(upload_to='documents/')
URL:
from django.conf.urls import url
from . import views
app_name = 'user'
urlpatterns = [
# upload
url(r'^upload/$', views.FileUploadView.as_view(), name='userform'),
# data preparation - dataframe creation
url(r'^datapreparation/$', views.DataPreparation.as_view(), name='datapreparation'),
]
HTML:
<div id="upload"></div>
<form class="dropzone" action="{% url 'user:datapreparation' %}" method="post" enctype="multipart/form-data" id="dropzone">{% csrf_token %}
<div>
Drop files here
</div>
</form>
<script>
(function() {
var form = document.querySelector('form');
var dropzone = document.getElementById('dropzone');
dropzone.ondrop=function(ev){
ev.preventDefault();
this.className='dropzone';
var data = new FormData(form);
var xhr = new XMLHttpRequest();
var file = ev.dataTransfer.files[0]
console.log(file)
xhr.open('POST', "/user/upload/")
data.append('file', file)
xhr.send(data)
};
dropzone.ondragover = function () {
this.className = "dropzone dragover";
return false;
};
dropzone.ondragleave = function () {
this.className = 'dropzone';
return false;
};
}());
The response from django is being handled by the javascript, so you you could return the URL in the django view (using for example the reverse method) and then window.location.href in the javascript.
You can check how to add a callback to XMLHttpRequest here
I believe you're missing the reverse mechanism on your redirect.
from django.urls import reverse
return redirect(reverse('user:datapreparation'))

Cannot append to formData object on file upload in React

I am new to react and I am attempting to upload a file to my node backend, but I've spent a while at this and cannot get it to work. I appear to send the data correctly to my handle function, but after that I cannot append it to my formData object.
Here is the function that I call on a handle submit button from my upload html.
uploadAction(){
var self = this;
console.log('inside uploadAction');
var data = new FormData();
// var filedata = {};
var filedata = document.querySelector('input[type="file"]').files[0];
data.append('file', filedata);
console.log('this is the value of data in uploadAction ', data);
console.log('this is the value of filedata in uploadAction ', filedata)
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
axios.post('http://localhost:5000/upload',{
filedata: data
},config)
.then((response)=>{
console.log('back again success from upload');
})
.catch((err)=>{
console.error('error from upload ', err);
});
So when I console log out the data and the filedata objects I get the following result.
this is the value of data in uploadAction FormData {}
this is the value of filedata in uploadAction File {name: "suck.jpg"....
So somehow it appears that my filedata is being brought in correctly, but there's a disconnect on how this being appended to the data object. Which I find confusing, as this seems to be the way I've found to append this data object from looking at these things online. I think my axios call is correct, but I am of course getting to an error before that.
Does anyone have any suggestions on how I can fix this? Is there an easier way to do this in react that doesn't involve using querySelector? I probably don't want to use dropzone or a similar library/package, I just want to learn how to do a simple upload file.
If anyone has any suggestions on this I would really appreciate it. I've spent some time on this and I seem to be going in circles.
EDIT: as per the suggestion of the first comment below I have added
for (var pair of data.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
to my code to try and console log my data value (ie the dataForm object). The result was:
file, [object File]
while this is true, it doesn't help fix my problem.
Change your call to the following way and it should work (data is your FormData):
axios.post('http://localhost:5000/upload',data,config)
In addition to it, as you are using React, instead of using querySelector, you could use the onChange event from your file input.
Just as an example:
import React,{Component} from 'react'
class UploadComponent extends Component {
constructor(props, context) {
super(props, context);
this.state = {file: null};
this.handleFileChange = this.handleFileChange.bind(this);
this.sendFile = this.sendFile.bind(this);
}
handleFileChange(event) {
this.setState({file:event.target.files[0]})
}
sendFile() {
//In here you can get the file using this.state.file and send
}
render() {
return(
<div>
<input className="fileInput" type="file" onChange={this.handleFileChange}/>
<button type="submit" onClick={this.sendFile}>Upload </button>
</div>
)
}
}

Ember-data RESTAdapter without JSON payload

In my Ember v2.7.0 app, I need to use backend endpoint which does not return JSON payload. But it behaves like REST endpoint, so I thought I would just use DS.RESTAdapter to fetch the data and convert the payload via DS.Serializer.
Created this little Ember-twiddle, which just tries to fetch data with non-JSON payload. And it fails. As far as I can tell, it fails in DS.RESTAdapter code, trying to extract JSON from the payload. So that my serializer does not have a chance to process the data.
This seems a bit odd, because I thought that Serializer is the layer which is responsible for munching the payload.
Is it possible to use DS.RESTAdapter for querying non-JSON endpoint?
If not, what is the easiest way to have REST-like behaviour on non-JSON endpoint?
What you'll need to do here is creating your own adapter that derives from DS.RESTRAdapter and then override its ajaxOptions-method. There you could change its dataType to text instead. I imagine that they separated this into its own method for your exact purpose since it doesn't do much else.
The Ember Guides have a page about customizing adapters that can get you started, based on the original code from the Ember repository it should probably be something like this.
import DS from 'ember-data';
import Ember from 'ember';
const {
get
} = Ember;
export default DS.RESTAdapter.extend({
ajaxOptions(url, type, options) {
var hash = options || {};
hash.url = url;
hash.type = type;
hash.dataType = 'text';
hash.context = this;
if (hash.data && type !== 'GET') {
hash.contentType = 'text/plain; charset=utf-8';
}
var headers = get(this, 'headers');
if (headers !== undefined) {
hash.beforeSend = function (xhr) {
Object.keys(headers).forEach((key) => xhr.setRequestHeader(key, headers[key]));
};
}
return hash;
}
});

Parsing JSON object sent through AJAX in Django

This is my code creating a json file:
$( ".save" ).on("click", function(){
var items=[];
$("tr.data").each(function() {
var item = {
itemCode : $(this).find('td:nth-child(1) span').html(),
itemQuantity : $(this).find('td:nth-child(4) span').html()
};
items.push(item);
});
});
Now the json object looks like:
[{"itemcode":"code1","itemquantity":"quantity1"},{"itemcode":"code2","itemquantity":"quantity2"},...]
My question is how do I parse this data in Django view?
Following is my AJAX function for reference:
(function() {
$.ajax({
url : "",
type: "POST",
data:{ bill_details: JSON.stringify(items),
calltype:'save'},
dataType: "application/json", // datatype being sent
success : function(jsondata) {
//do something
},
error : function() {
//do something
}
});
}());
Since I'm sending multiple AJAX request to the same view, I need the 'calltype' data as well.
Thanks you on your answer!! BTW, I badly need to know this simple stuff, which I'm missing
This is my code snippet for parsing:
if (calltype == 'save'):
response_data = {}
bill_data = json.loads(request.POST.get('bill_details'))
itemcode1=bill_details[0]['itemCode']
#this part is just for checking
response_data['name'] = itemcode1
jsondata = json.dumps(response_data)
return HttpResponse(jsondata)
The error being raised is
string indices must be integers
Request your help
For your reference, this is my POST response (taken from traceback):
bill_details = '[{"itemCode":"sav","itemQuantity":"4"}]'
calltype = 'save'
csrfmiddlewaretoken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
EDITED Django View
This is my edited view:
if (calltype == 'save'):
bill_detail = request.POST.get('bill_details')
response_data = {}
bill_data = json.loads(bill_detail)
itemcode1=bill_data[0]['itemCode']
#this part is just for checking
response_data['name'] = itemcode1
jsondata = json.dumps(response_data)
return HttpResponse(jsondata)
I fail to understand the problem. SO, to solve it, my question: what is the datatype of the return for get call and what should be the input datatype for json.loads. Bcoz the error being shown is json.loads file has to be string type!! (Seriously in limbo)
Error:
the JSON object must be str, not 'NoneType'