Is it better to retrieve data through AJAX or returning it alongside view from Controller (Laravel)? - ajax

So the scenario is getting data we need from controller and using it in our view. But there are two options, you can have either this line in your "show" method:
UserController#show
return view('webpage');
And in the 'webpage' you can send an Ajax request to UserController#fetch and get that data. Or you can get the data from database in UserController#show and then send it alongside view like this:
UserController#show
return view('store', compact('store'));
But which is the more efficient and secure way of doing this?

It really depends on what you're doing, if the data you're requesting and the process you're running takes a lot of time or in a future it would, ajax is the way to go, but if process is short and the requested data from your model is small, then you can request it on the same method that returns your view and send the data to it.

Related

Dynamically add form to formset in Django and submit with AJAX

I have read a lot of answers relating to how to dynamically add forms to an model formset in Django and can successfully implement that. However, I would now like to submit the formset with AJAX. This is mostly working now but I have an issue that I can't find a solution to in any other answer:
If you dynamically add a form to the formset, you give it a new form id number that is one larger than the maximum the form currently has and you also increment the management TOTAL_FORMS count by one. The newly added form then saves successfully as a new object.
I am trying to submit by AJAX so the user can continue editing without having the page refresh. The formset saves fine but any dynamically added forms are now existing objects. To account for this I need to increment the INITIAL_FORMS count on the management form when the save is successful. Easy enough. However, I've also realised I need to give the newly created objects an ID since they now exist in the database.
How can I get my view to tell me the ID of the new objects in its response to the AJAX call? Or is there a better way of looking at this?
Django forms and formsets are intended for classic browser-based posting of data. Though they can definitely be made to work with Javascript, the more you want to part from the normal behavior, the more complex it gets.
Depending on your requirements, you might start thinking about dropping it and switch to Javascript + REST endpoint. Of course, if you need progressive enhancements and you are required to have it work without javascript, that's not an option.
In any case, you want to have a customized view for posting from JS, so that you can get the result back and parse it easily in your AJAX handler. Probably some JSON.
There are several approaches you could take.
Have your AJAX send data to a different URL. This is pertinent if you have an API or are planning to build one at some point. So your form, when submitted normally, will do its old-style processing but your AJAX will talk to the API endpoint instead.
For instance, your form send to https://example.com/myform, but your Javascript code talks to REST api at https://example.com/api/v1/mymodel/ (sending PUT, POST and DELETE requests as appropriate).
Or if you don't have an API and building one seems overkill, you may just alter your view so it formats its output differently depending on whether the data is being submitted in the regular way or using AJAX.
You'd go about it like this:
class MyFormView(.....):
def render_to_response(self, context, **kwargs):
if self.request.is_ajax():
return self.render_to_json(context, **kwargs)
return super().render_to_response(context, **kwargs)
def render_to_json(context, **kwargs):
data = {
# see below!
}
return HttpResponse(
content=json.dumps(data).encode('ascii'),
content_type='application/json',
)
This is just an outline. You need to ensure is_ajax will detect it properly (see django doc). And you need to properly build data from context: extract the things you want to send back to your JS code and put them in the dict.
You will find it's manageable if you just do this for one, maybe two views in your project, but very quickly you'll want to have a small API instead, especially given how easy it is to build one with packages such as Django REST framework.
In your view, where you save the object, AFTER the save, the object.id will contain the new id for the object, which you can return via json or however you want in your ajax response, and then yes you will need to fill that into the formset row so that it will be submitted the next time.
One thing you have to watch out for is that django expects all existing rows to be at the top of the formset, and any new rows to be at the bottom. Otherwise, the formset save will complain about missing id's. So if you're doing any kind of sorting in your javascript, you can't do that.. unless you do quite a bit of fixing of all the field names etc in the formset. The formset code uses the numbers in the management form to determine which rows to insert and which rows to update, it does not do it on the basis of whether or not an id is present. Unfortunately...

Save original response data and replace them using MVC

I need to get response data (incuding html markup) on server and then replace them to anothe one and send to the client.
Is where the best way to do this?
Response.OutputStream is closed for reading.
So what can I use for reading data?
I need to get response data (incuding html markup) in controller
For obvious reasons that's not possible. The response HTML is generated when the view executes, at a much later stage after the controller action has finished executing.
If you want to modify the response HTML you could write a response filter.

What is the difference between "render a view" and send the response using the Response's method "sendResponse()"?

I've asked a question about what is "rendering a view". Got some answers:
Rendering a view means showing up a View eg html part to user or
browser.
and
So by rendering a view, the MVC framework has handled the data in the
controller and done the backend work in the model, and then sends that
data to the View to be output to the user.
and
render just means to emit. To print. To echo. To write to some source
(probably stdout).
but don't understand then the difference between rendering a view and using the Response class to send the output to the user using its sendResponse() method. If render a view means to echo the output to the user then why sendResponse() exists and vise versa? sendResponse() exactly sends headers and after headers outputs the body. They solve the same tasks but differently? What is the difference?
In ZF, rendering a view doesn't actually output any content. Instead the rendering process returns the content as a string to the caller. Zend_Application automatically takes care of taking the rendered view and inserting it into your layout (assuming you use layouts) through a placeholder, and putting that data into the Zend_Controller_Response_Http object which is ultimately responsible for delivering the content to the user. The reason for the Response object is so it can encapsulate your HTML output, and also manage any additional HTTP headers or redirects you want to send.
You can also manipulate further the contents of the response in the Response object prior ot sending the data to the client if you wish.
sendResponse() takes care of sending any headers (including the HTTP response code), checking for any exceptions that may have occurred (due to not being able to send headers or other reasons) and then sends the HTML which could include your layout and one or more rendered view scripts.
Hope that helps.
They are two very different things.
Rendering a view provides another layer in which you can template your data. This will allow you to easily dynamically populate HTML/templates keeping logic seperate from presentation.
Echoing data directly skips this step, and is usally reserved for reterning json/xml (data) responses to user instead of html response.
You didn't post which framework you are talking about but both should allow you to specify response headers.
Please don't oversimplify. Every server's purpose is to render resource but that doesn't mean they are all the same.

Client side to server side calls

I want to change the list of available values in a dropdown depending on the value selected in another dropdown and depending on values of certain fields in the model. I want to use JQuery to do this. The only hard part is checking the values in the model. I have been informed that I can do this using Ajax. Does anyone have any idea how I will approach doing this?
AJAX is indeed the technology your looking for. It is used to sent an asynchronous request from the client browser to the server.
jQuery has an ajax function that you can use to start such a request. In your controller you can have a regular method tagged with the [HttpPostAttribute] to respond to your AJAX request.
Most of the time you will return a JSON result from your Controller to your view. Think of JSON as something similar to XML but easier to work with from a browser. The browser will receive the JSON and can then parse the results to do something like showing a message or replacing some HTML in the browser.
Here you can find a nice example of how to use it all together.

Hiding Query String Parameters

I have a GET action for creating records. Because the page is somewhat dynamic, I don't use a model to hold the data. I go off to do some OAuth, only to return to the create screen later on. In order to pass the data back, I am redirecting with a query string. I parse the query string in the GET action, and then show the view. The thing is, the query string is showing up in the browser. This displays pseudo-sensitive data.
Since I am only using the query string for transferring data, I am wondering if I can throw the query string away to prevent it from showing up on the browser.
Otherwise, is there a way to go to another action without redirecting? I've found, if I call the "other" action method directly, it tries to find the view of the original action. I can explicitly change the return View(viewModel) line to return View("create", viewModel) but that seems really dirty.
You should consider changing the action to accept POST requests. At least this will prevent the sensitive information from appearing in the browser. For extra security, your site should be served via SSL.
The other thing you can try is encrypting the sensitive values or the entire query string. The only problem is that this, too, will be preserved in the browser's history unless you require users to log in.
It looks like your action method is trying to do too much. Authentication/authorization is a separate concern which should not be part of the action method. It is better to move the authentication work in to an action filter.
Create an class that extends authorization attribute and override its OnAuthorization method to do your authorization work.
This frees your controller action method to accept POST requests.

Resources