Context from Django Render Not Displaying Till Refresh? - ajax

I am using an AJAX call to POST a value to my views.
From my views I am finding the product based on the value(id) passed to my view. I add it to my invoice and apply it to my context which I render at the bottom of my view. The context will not be displayed until I refresh, but I can't have that. I am stuck.
...
elif request.is_ajax():
product_id = request.POST.get('value')
if product_id:
product_info = Product.objects.get(id=product_id)
new_invoice_product = InvoiceProduct.objects.create(invoice_product_set=product_info)
invoice.attached_products.add(new_invoice_product)
context['attached_products'] = invoice.attached_products.all()
...
return render(request, 'inventory/invoice_create.html', context)

You can't just re-render client's HTML DOM by your server directly.
Through DjangoTemplate Engine, it just render then respond with HTML itself. This means you can't update client's DOM with ajax unless you update root element, <html>. (and this will be as same as reloading page!)
So you may want to update DOM tree with some data, do with ajax call then update with jsonfile only. If you use JsonResponse, then you can get it with AJAX response object.
Then What you have to do is NOT django template but JavaScript programming.
In your views.py, do like this:
# in your views.py
...
elif request.is_ajax():
product_id = request.POST.get('value')
if product_id:
product_info = Product.objects.get(id=product_id)
new_invoice_product = InvoiceProduct.objects.create(invoice_product_set=product_info)
invoice.attached_products.add(new_invoice_product)
context['attached_products'] = invoice.attached_products.all()
# return render(request, 'inventory/invoice_create.html', context) # NOT render but do like this:
return JsonResponse({
'new_data': {
'id': new_invoice_product.id
# and other informations you want...
}
})
In your HTML, do like this:
<script src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script>
// in your HTML
// guessing you're using jquery..
$.ajax({
url: "test.html",
context: document.body
}).done(function (json) {
$('yourSelector').append(json['new_data']['id']);
});
</script>
Remember, this code is just snippet not Fully working code. If you want to know further examples, take a look at link:
https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html

Related

How to submit data to Flask from an Ajax call, and return its response in Flask from another Ajax call?

Sorry if the title is a little confusing. A kind user here on StackOverflow helped me make my Flask app display some scraped data, only now I have added a parameter in the function so that I can scrape the data I want to search for. I have an input box, and I want to be able to get the data from it, and pass it as a string in my python function in Flask
Current HTML Side
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "utf-8">
<title>NBA Data Web App</title>
</head>
<body>
<script src = "http://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" crossorigin = "anonymous"></script>
<form id = "nameForm" method = "POST" role = "form">
<input name = "text">
<button id = "searchBtn"> Search </button>
</form>
<div id = "container"></div>
<script type = "text/javascript">
//Function to take place when our search button is clicked
$('button#searchBtn').click(function() {
$.ajax({
url: '/_get_data',
data: $('form').serialize(),
type: 'POST',
success: function(response) {
console.log = response;
},
error: function() {
alert('Failure in first Ajax call');
}
});
/*Everything below this was working before, as I only made one ajax call when a button was pressed. Now, when I press the button, I want to pass its contents as a string to my scrape_data() function in Flask, and return, and display, its contents as shown below. */
//Declare our list so we can print something, and loop through it later
var data_list;
//Variable for our HTML table
var rowMax = 29, html = "<table><tr>";
//Post request
$.post('/_get_data', {
//If done, do this
}).done(function(response) {
/* Assign our scraped data to our variable that was declared earlier,
which is turned into an array here in JS */
data_list = response['data'];
//Declare some variables for making our table
var perRow = 1, count = 0, table = document.createElement("table"),
row = table.insertRow();
//Loop through the data and add it to the cells
for (var i of data_list) {
//Insert a cell for each piece of data
var cell = row.insertCell();
//Add the data to the cell
cell.innerHTML = i;
//Increment our count variable
count++;
//If we have met our set number of items in the row
if (count % perRow == 0) {
//Start a new row
row = table.insertRow();
}
}
//Add the table to our container in our HTML
document.getElementById("container").appendChild(table);
//If request fails
}).fail(function() {
alert("request failed");
});
});
</script>
</body>
</html>
Python (Flask) Side
rom flask import Flask, render_template, jsonify, request, escape, url_for
#Get our lists to post
headers = data_headers()
#Start the flask app
app = Flask(__name__)
#Start page
#app.route('/')
def index():
return render_template('index.html')
#What happens when our button is clicked
#app.route('/_get_data', methods = ['POST'])
def _get_data():
text = request.form['text']
#Here, I am trying to assign the contents of the input box of the form to a variable, so I can pass that variable as a parameter for my function.
data = scrape_data(text)
#Return the json format of the data we scraped
return jsonify({'data' : data})
#Run the app
if __name__ == "__main__":
app.run(debug = True)
I am currently getting error 405 method not allowed. I'm not sure if my syntax in the first Ajax call is incorrect, or if I need to break this up into two different #app.route(urls) since each call is going a different way.
If you use the method attribute of form element and do not specify the action, request will be sent /. What is happening here is when you click on search button it will send two post requests one to '/' and '/_get_data' from ajax. In Flask routing if you do not explicitly provides methods=[] that route will allow GET only. Remove the method attribute from you form, you should not get method not allowed error.

Grails Render Partial Template to Div

I have a form page where the user selects a filter and a table on the bottom of the page updates. Each line in the table has a hyperlink in column one that associates a line item to an item in the database. I am not using GORM.
I need to be able to send the current filters to the controller via AJAX (functioning). Then I need to render a partial template (to a div) that loads the data created by a query based on the client's request parameters.
GSP:
....
<button onClick="generate_table()" class="pure-button">Generate Table</button>
...
<div id="selection_table">This should load with data</div>
...
JS:
//Link for AJAX
var url = "${g.createLink(action:'generate_table', controller: "statusReports")}";
//The actual call
$.getJSON(url, {
period: JSON.stringify($("#period").val()),
...
...
}, function(data) {
$('#selection_table').empty();
}).done(function(data) {
//I need to load the template at this point?
})
Controller:
def generate_table(){
def table_data = statusReportsService.generate_titles(params)
// Table data is already a map
// What do I need to render here? The template is named _selectionTable.gsp and should use table_data to generate html.
}
Partial:
I still haven't written the code for this yet. For now it is just some random text to see if I can even load the template when I press the button
In your controller:
render(template: 'selectionTable', model: table_data)
In your GSP/HTML you need to use $.get and use the following:
$('#selection_table').html(data)
That should do the trick!

Refresh form in Django without reloading page

Hi I'm new in Ajax and django and I want to refresh my form. I try some code but it didn't work. I'm sure what I want to do is very basic.
Here my html:
<div class="row" style="padding-top:20px;">
<div class="col-md-12" id="testAjax">
{% load crispy_forms_tags %}
{% crispy form %}
</div>
</div>
I want to refresh my form in the div testAjax.
Here my view:
def createPin(request):
error = False
if request.method == "POST":
form = CreatePinForm(request.POST)
if form.is_valid():
pin = form.save(commit=False)
pin.customer = request.user.customer
pin.save()
msg = "pin saved"
return redirect('/pin/CreatePin', {'form': form, 'msg': msg})
else:
error = True
else:
form = CreatePinForm()
return render(request, 'createPin.html', {'form': form, 'error': error,})
My Ajax:
function refresh()
{
$form=$('#createPin');
var datastring = $form.serialize();
$.ajax({
type: "POST",
url: '/pin/CreatePin/',
dataType: 'html',
data: datastring,
success: function(result)
{
/* The div contains now the updated form */
$('#testAjax').html(result);
}
});
}
Thanks alot for your help.
When I need to do some operations and I don't want to reload the page I use a JQuery call to Ajax, I make the pertinent operations in AJAX and then receive the AJAX response in the JQuery function without leaving or reloading the page. I'll make an easy example here for you to understand the basics of this:
JQuery function, placed in the template you need
function form_post(){
//You have to get in this code the values you need to work with, for example:
var datastring = $form.serialize();
$.ajax({ //Call ajax function sending the option loaded
url: "/ajax_url/", //This is the url of the ajax view where you make the search
type: 'POST',
data: datastring,
success: function(response) {
result = JSON.parse(response); // Get the results sended from ajax to here
if (result.error) { // If the function fails
// Error
alert(result.error_text);
} else { // Success
//Here do whatever you need with the result;
}
}
}
});
}
You have to realize that I cannot finish the code without knowing what kind of results you're getting or how do you want to display them, so you need to retouch this code on your needs.
AJAX function called by JQuery
Remember you need to add an url for this Ajax function in your urls.py something like:
url(r'^/ajax_url/?$', 'your_project.ajax.ajax_view', name='ajax_view'),
Then your AJAX function, it's like a normal Django View, but add this function into ajax.py from django.core.context_processors import csrf from django.views.decorators.csrf import csrf_exempt from django.utils import simplejson
#csrf_exempt
def ajax_view(request):
response = []
#Here you have to enter code here
#to receive the data (datastring) you send here by POST
#Do the operations you need with the form information
#Add the data you need to send back to a list/dictionary like response
#And return it to the JQuery function `enter code here`(simplejson.dumps is to convert to JSON)
return HttpResponse(simplejson.dumps(response))
So, without leaving the page you receive via javascript a list of items that you sended from ajax view.
So you can update the form, or any tag you need using JQuery
I know that this can be so confusing at the beginning but once you are used to AJAX this kind of operations without leaving or reloading the page are easy to do.
The basics for understanding is something like:
JQuery function called on click or any event you need
JQuery get some values on the template and send them to AJAX via
POST
Receive that information in AJAX via POST
Do whatever you need in AJAX like a normal DJango view
Convert your result to JSON and send back to the JQuery function
JQuery function receive the results from AJAX and you can do
whatever you need

AJAX call with nodeJS and express successful, but not displaying data

I have recently migrated from a codeigniter framework, to a nodejs with an express framework. Our codeigniter site had a lot of JS as it was, and we made a lot of AJAX calls because it is a single page app. We are messing around with node and express now, and I cannot get a simple AJAX call to function. It could be a lack of understanding of node, it could be something else. We are using openshift to host. We are using hogan-express as a template.
server.js
var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var SampleApp = function() {
var self = this;
self.initializeServer = function() {
self.app = module.exports = express();
self.app.configure(function() {
self.app.set('views', __dirname + '/views');
self.app.set('view engine', 'html');
self.app.engine('html', require('hogan-express'));
//self.app.set('layout', 'layout') # use layout.html as the default layout
self.app.use(express.favicon());
self.app.use(express.logger('dev'));
self.app.use(express.bodyParser());
self.app.use(express.methodOverride());
self.app.use(express.session());
self.app.use(self.app.router);
self.app.use(require('stylus').middleware(__dirname + '/public'));
self.app.use(express.static(path.join(__dirname, 'public')));
});
require('./routes');
}
There is more code in this file, I am only including the relevant code (I think).
Ajax.html
<div id="button">
<button id="testbutton">Push Me!</button>
</div>
<div id="populate">{{title}}</div>
<div id="null">{{>part}}</div>
<script type='text/javascript'>
$(function(){
$('#testbutton').click(function (){
$.ajax({
url:'/test',
type: 'POST',
success: function(result){
alert('success!');
},
error: function(){
alert("well this is embarassing... if the problem persists please let us know at facebook.com/stembuds");
}
});
});
});
</script>
index.js
app = require('../server');
app.get('/', function(req, res){
res.render('ajax');
});
app.post('/test', function(req, res){
console.log('get');
res.locals = {title: 'Horray'};
res.render('ajax', {partials:{part:'part'}});
});
part.html
<p> pass me in!!</p>
So basically what I am trying to do is when the button is clicked I want the ajax call to show a partial view. The way we are going to structure the site is to have one single page, and have the ajax calls render different views based on the buttons that the user clicks. So here is the interesting part: I get the success alert from the ajax call, but the {{title}} and the {{>part}} never show up. However, when I go to the console and click 'network', and then click 'test' (the url to my ajax call), the response shows the divs populated with "Horray" and "pass me in!!". Sorry for the length, and thank you for any information you can provide us.
If you are calling your resources with ajax (as you are doing) then you get the response to your ajax function. After successful call you need to render the view in your client side JS code.
What I mean is that your code works as expected, but your backend cannot update your browsers view. You need to do it client side or load the whole page again from the server.
Your success hander could be something like this:
success: function(result){
renderTheResults(result);
},
You can just send the JSON. You need to send the json via send not render. Because render is supposed to deliver the full HTML page. May be .ejs file.
For example:
res.send({partials:{part:'part'}});
res.send should be used to pass json to your page. And on your page you have to use the JSON to populate the HTML dynamically.

How do I render a view after POSTing data via AJAX?

I've built an app that works, and uses forms to submit data. Once submitted, the view then redirects back to display the change. Cool. Django 101. Now, instead of using forms, I'm using Ajax to submit the data via a POST call. This successfully saves the data to the database.
Now, the difficult (or maybe not, just hard to find) part is whether or not it's possible to tell Django to add the new item that has been submitted (via Ajax) to the current page, without a page refresh. At the moment, my app saves the data, and the item shows up on the page after a refresh, but this obviously isn't the required result.
If possible, I'd like to use exactly the same view and templates I'm using at the moment - essentially I'd like to know if there's a way to replace a normal HTTP request (which causes page refresh) with an Ajax call, and get the same result (using jQuery). I've hacked away at this for most of today, so any help would be appreciated, before I pull all of my hair out.
I had a very similar issue and this is how I got it working...
in views.py
from django.utils import simplejson
...
ctx = {some data to be returned to the page}
if ajax == True:
return HttpResponse(simplejson.dumps(ctx), mimetype='json')
then in the javascript
jQuery.ajax({
target: '#id_to_be_updated',
type: "POST",
url: "/",
dataType: 'json',
contentType: "text/javascript; charset=\"utf-8\"",
data: {
'foo':foo,
'bar':bar,
},
success: function(data){
$("#id_to_be_updated").append(data.foo);
}
});
Here's how I did it:
The page that has the form includes the form like so
contact.html
{% include "contact_form.html" %}
This way it's reusable.
Next I setup my view code (this view code assumes the contact form needs to be save to the db, hence the CreateView):
class ContactView(CreateView):
http_method_names = ['post']
template_name = "contact_form.html"
form_class = ContactForm
success_url = "contact_form_succes.html"
There are a few things to note here,
This view only accepts pots methods, because the form will be received through the contact.html page. For this view I've setup another template which is what we included in contact.html, the bare form.
contact_form.html
<form method="POST" action="/contact">{% crsf_token %}
{{ form.as_p }}
</form>
Now add the javascript to the contact.html page:
$("body").on("submit", 'form', function(event) {
event.preventDefault();
$("#contact").load($(this).attr("action"),
$(this).serializeArray(),
function(responseText, responseStatus) {
// response callback
});
});
This POSTS the form to the ContactView and replaces whatever is in between #contact, which is our form. You could not use jquery's .load function to achieve some what more fancy replacement of the html.
This code is based on an existing working project, but slightly modified to make explaining what happens easier.

Resources