Send a queryset of models from Django to React using Ajax - json

I've been looking for info about this for hours without any result. I am rendering a page using React, and I would like it to display a list of Django models. I am trying to use ajax to fetch the list of models but without any success.
I am not sure I understand the concept behind JSon, because when I use the following code in my view:
data = list(my_query_set.values_list('categories', 'content'))
return JsonResponse(json.dumps(data, cls=DjangoJSONEncoder), safe=False)
It seems to only return a string that I cannot map (React says that map is not a function when I call it on the returned object). I thought map was meant to go through a JSon object and that json.dumps was suppose to create one...
Returned JSon "object" (which I believe to just be a string):
For the time being I have only one test model with no category and the content "At least one note "
[[null, "At least one note "]]
React code:
$.ajax({
type:"POST",
url: "",
data: data,
success: function (xhr, ajaxOptions, thrownError) {
var mapped = xhr.map(function(note){
return(
<p>
{note.categories}
{note.content}
</p>
)
})
_this.setState({notes: mapped})
},
error: function (xhr, ajaxOptions, thrownError) {
alert("failed");
}
});
Can someone please point me to the best way to send Models from Django to React, so I can use the data from this model in my front end?

I recommend using the Django REST Framework to connect Django to your React front-end. The usage pattern for DRF is:
Define serializers for your models. These define what fields are included in the JSONified objects you will send to the front-end. In your case you might specify the fields 'categories' and 'content.'
Create an API endpoint. This is the URL you will issue requests to from React to access objects/models.
From React, issue a GET request to retrieve a (possibly filtered) set of objects. You can also set up other endpoints to modify or create objects when receiving POST requests from your React front-end.
In the success function of your GET request, you will receive an Array of Objects with the fields you set in your serializer. In your example case, you would receive an Array of length 1 containing an object with fields 'categories' and 'content.' So xhr[0].content would have the value "At least one note ".
In your code, the call to json.dumps within the JsonResponse function is redundant. Check out the docs for an example of serializing a list using JsonResponse. If you are serializing the object manually (which I don't recommend), I'd use a dictionary rather than a list -- something like {'categories': <value>, 'content' : <value>}. DRF will serialize objects for you like this, so the fields are easier to access and interpret on the front-end.

Related

How to: (a) send JSON data from the browser to the controller; and (b) send the transformed data to SQL Server within ASP.NET MVC?

I have a form which includes a variety of <input> elements and makes use of 1-to-n tabulator tables for data input. I have managed to successfully assemble data from these elements into a JSON string. I am now attempting to complete the following two steps:
Using Ajax, post the JSON object to my web server; and
In the ASP.NET MVC controller, upload the deserialized JSON data into a SQL Server 2016 table.
My client-side script to POST the JSON object is as follows:
var myJson = "the data from the form elements is programmatically inserted into the JSON string";
// use parseJSON() to test the syntax
try {
var obj = jQuery.parseJSON(myJson);
}
catch(error) {
console.log(error);
}
$.ajax({
type: "POST",
url: "/Dailies/UploadJson/",
dataType: 'json',
data: JSON.stringify(myJson),
contentType: 'application/json',
crossDomain: true,
cache: false,
success: function(data) { console.log(data); }
});
The method called within my ASP.NET MVC controller appears as follows:
[HttpPost]
public IActionResult UploadJson(Object jsonFile)
{
// insert data into SQL Server table
}
Note: I have already created the appropriate domain model within my ASP.NET MVC app and have also added a DbSet reference to the DbContext model. I have verified my ability to insert rows into the SQL Server table using mock data.
When I place a breakpoint inside the UploadJson() method, I find that the jsonFile object is null.
My quandry at this point is two-fold:
I can't seem to get JSON data from the client to the web server; and
I need to better understand how to transform the JSON data (once received) for upload into my database.
Any assistance is greatly appreciated.
Although there are plenty of questions related to this, the answers to those typically refer to binding to a model instead of just the json string. But those will also help you.
It looks like there are two things:
I would change the controller to receive a string instead of an object.
You'll need to update the json data you're passing to the controller to match the parameter name of the controller. So in this case, the controller would receive a parameter named jsonFile. So in the $.ajax method you'll want update the data to something like:
data: { jsonFile: JSON.stringify(myJson) }
UPDATE:
remove the Content-Type of application/json

Django - How to render html and return a json at the same time

I have a view which populate a json object, and then, at the end of the same view I would render an html page, but also return the final json.
probably this is not relevant but the json would be for example something like this:
{
"embedToken": "dasfgjasdàgjasdàgasdàgèe-AveryLongToken",
"embedUrl": "https://app.powerbi.com/let's_go_to_the_lake",
"reportId": "e615-sfash-9746"
}
the line I'm not able to fix (tried all day with all alternatives methods) is the following:
return render(request, "home.html", jsn)
my url.py is simple as follow:
urlpatterns = [
path('', HomePageView, name='home'),
]
I currently get the following error:
context must be a dict rather than str.
But I encountered all different kinds of errors on the way without succeeding to reach the desired result(rendering the html and returning the json at the same time). So my doubt is that I'm taking the wrong approach at the basics, should I change road?
I would like to try to convert the json into a dictionary, and then maybe convert it back in a json in JavaScript
I have also tried to split my requests, by rendering the html as a Django view, and performing the function call from JavaScript ajax request as follow:
function handler1(){
// there are many other methods like $.get $.getJSON
$.ajax({
type: 'GET',
dataType: 'json',
url: "http://piedpiper.com/api/callers"
}).then(function(result) {
// do something with the result
});
}
But I ended up by understanding that in this way I must create the URL api/callers which will be available/reachable to everybody, which I cannot do, because of the user session. only the logged in user must see the json data
You need to add the proper arguments on render. Here is the docs for render function in Django
Here is a sample code of a view
def post_detail(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
share_string = quote_plus(instance.content)
context = {
"title": instance.title,
"instance": instance,
"share_string": share_string,
}
return render(request, "post_detail.html", context)

Send both JSON response and model in Grails

I'm new to Grails and I'm stuck up with a problem. I want to know if there is a way to send both JSON and view and model through "render" in Grails.
I'm using a jQuery Datatable to display data returned from server which is read from JSON returned by the controller. I also need to display error messages on the same view in case of validation failure in form fields. But I'm able to return either only the JSON or model and view using render. I also tried sending the JSON through model itself but it didn't work.
This is my code:-
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance]);
//render json;
The gsp code:-
<g:hasErrors bean="${hierarchyBreakInstance}">
<div class="errorMessage" role="alert">
<g:eachError bean="${hierarchyBreakInstance}" var="error">
<g:if test="${error in org.springframework.validation.FieldError}" > data-field-id="${error.field}"</g:if>
<g:message error="${error}"/>
</g:eachError>
</div>
</g:hasErrors>
Could you please let me know if there is a way to do this. Thanks!
You can use like this.
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance,json:json]);
//render json;
Assuming that you are doing a request with some parameters, and need to return if was succesfull or not, and the data to fill the table with ajax.
I will do on that way, use the statuses of the HTTP to mark if it was a problem with the validation(normally we return 400 Bad Request and the message)
Example :
return ErrorSender.sendBadRequest("error validating field $field with value $value")
And the errorsender has a sendBadRequest method
[response: ['message': message, error: "bad_request", status: 400, cause: []], status: 400]
If the request was OK, you only need to respond the data with something like
return [response: results, status: 200]
In the client side you have to have one function if the request was OK to parse result, and one function if request have some validated data problem, database problem or whatever that caused that the request didn´t return a 200(in the example),there are more status codes, you can check on
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
PD: Initial validation should be done on client side.

PUT requests with Custom Ember-Data REST Adapter

I'm using Ember-Data 1.0.0.Beta-9 and Ember 1.7 to consume a REST API via DreamFactory's REST Platform. (http://www.dreamfactory.com).
I've had to extend the RESTAdapter in order to use DF and I've been able to implement GET and POST requests with no problems. I am now trying to implement model.save() (PUT) requests and am having a serious hiccup.
Calling model.save() sends the PUT request with the correct data to my API endpoint and I get a 200 OK response with a JSON response of { "id": "1" } which is what is supposed to happen. However when I try to access the updated record all of the properties are empty except for ID and the record on the server is not updated. I can take the same JSON string passed in the request, paste it into the DreamFactory Swagger API Docs and it works no problem - response is good and the record is updated on the DB.
I've created a JSBin to show all of the code at http://emberjs.jsbin.com/nagoga/1/edit
Unfortunately I can't have a live example as the servers in question are locked down to only accept requests from our company's public IP range.
DreamFactory provides a live demo of the API in question at
https://dsp-sandman1.cloud.dreamfactory.com/swagger/#!/db/replaceRecordsByIds
OK in the end I discovered that you can customize the DreamFactory response by adding a ?fields=* param to the end of the PUT request. I monkey-patched that into my updateRecord method using the following:
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var adapter = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
// hack to make DSP send back the full object
adapter.ajax(adapter.buildURL(type.typeKey) + '?fields=*', "PUT", { data: data }).then(function(json){
// if the request is a success we'll return the same data we passed in
resolve(json);
}, function(reason){
reject(reason.responseJSON);
});
});
}
And poof we haz updates!
DreamFactory has support for tacking several params onto the end of the requests to fully customize the response - at some point I will look to implement this correctly but for the time being I can move forward with my project. Yay!
EmberData is interpreting the response from the server as an empty object with an id of "1" an no other properties in it. You need to return the entire new object back from the server with the changes reflected.

Get custom JQGrid JSON data in gridComplete method

Here is a typical JQGrid JSON response:
{
"page":1,
"records":537,
"rows":[..],
"rowCount":10,
"total":54
}
Along with this, I want to send additional custom data. For example, I'd like to send the database time of the last search so that I can lazy-reload my grid whenever changes have occurred since then. Here is how I would like to send that data:
{
//Custom name-value pairs:
"nameValues":{"lastSearchTime":"2011/09/01:14:14:56"},
//Normal JSON data:
"page":1,
"records":537,
"rows":[..],
"rowCount":10,
"total":54
}
The problem is that JQGrid swallows up the JSON response rather than forwarding it to the gridComplete method. In other words, params is undefined in the following function:
function myGridComplete (params){
//params is undefined!
var JSONResponse = ?;//I need your help here!!!
globalGridVariables.lastSearchTime = JSONResponse.nameValues.lastSearchTime;
//Rest of grid complete method
..
}
Please let me know if there is a way to get access to the JSON response object in the gridComplete method, or if there is another supported way to add custom data to a JSON response.
Thanks much!
Note: I don't want to send this as a hidden column, because that would be inefficient.
You can use loadComplete instead of gridComplete. The loadComplete event has one parameter (for example data) which represent the full data from the server response inclusive all of your extensions.
Alternative you can rename the nameValues to userdata and use $('#list').jqGrid('getGridParam', 'userData') to get the value. See here for more information.
Moreover you can consider to use more HTTP caching (see here and here) for the aims which you described in your question.
You can use beforeProcessing that has the deserialized response and gets active before gridComplete and loadComplete.
For example:
beforeProcessing: function (data, status, xhr) {
myArray = data.rows;
}
And just to make it more clearer from the documentation:
Below is the execution order of the events when a ajax request is made
beforeRequest
loadBeforeSend
serializeGridData
loadError
beforeProcessing
gridComplete
loadComplete