send data from flask to html with 2 forms - javascript

I have flask sending data to html. Now, first time it does that its by render_template('page1.html', data=data) which populates the main table. Now when i click on any row of main table, i want to call flask again by url_for(entrypoint) and then again i will do render_template('page1.html', data=data2) for the 2nd table. But how to differentiate between them? i mean how will html know which data is coming for whom? please advice. I am novice in javascript and html. I am planning to keep the main table and secondary table under different forms. please advice if thats good decision or not.
Inside my html(page1.html), I have written
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
function getId(element) {
var row_index=element.rowIndex;
$.ajax({
url: '/get_details',
data: document.getElementById("table1").rows[row_index].cells[5].innerHTML),
type: 'POST',
success: function(response){
console.log(response);
},
error: function(error){
console.log(error);
}
});
This is the code in html for table1 and table2(table2 not done yet)
<section id="boxes" style="margin-top:-5%; margin-bottom:0%; position:absolute; z-index:1;">
<div class="box" style="margin-left:30px; margin-top:20px; z-index:1;">
<table id="table1">
<tr>
<th>NO</th>
<th> SUBJECT NAME</th>
<th>ASSIGNED TO</th>
<th>CREATED</th>
<th>DISEASES</th>
<th>SUBJECT ID</th>
<th>STATUS</th>
</tr>
{% for row in data %}
<tr onclick="getId(this)">
<td> {{ row[0] }}</td>
<td> {{ row[1] }}</td>
<td> {{ row[2] }}</td>
<td> {{ row[3] }}</td>
<td> {{ row[4] }}</td>
<td> {{ row[5] }}</td>
<td> {{ row[6] }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="box-two">
</div>
Inside my app.py
here is the flask code for the entry point:
#app.route('/get_details', methods=['POST'])
def get_details_user(patientid):
print(patientid)
This is the code for the entrypoint for the records which populates table1 as of now:
#app.route('/records')
#login_required
def records():
if current_user.priviledge:
data = get_records_by_userid(None)
else:
data = get_records_by_userid(current_user.id)
list_data = []
for row in data:
list_data.append([])
for col, val in row.items():
list_data[-1].append(val)
return render_template('records.html', data=list_data)
I don't see this in my flask code being triggered. Something wrong in my ajax code?? Also, how do I get the data from flask to this same html file for the second table?
Thanks a lot,
Sudip

Update: The error was coming due to ajax function syntax. Went with extra ')' in data in ajax...oops, thats bad

Add this to the JAvascript code:
$.ajax(function() {
headers = {'X-CSRFToken' : $('#csrf_token').val() },
...
});
This is the token the allows AJac to be validated

Related

Sending data to database with JavaScript in Django

I need to write a compatible algorithm for this code, but I can't. How can I send data to backend?
I am using bootstable.js for table
HTML table:
<table class="table table-bordered" id="table-list">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Slug</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{% for chart in charts %}
<tr>
<th id="id">{{chart.id}}</th>
<td class="editable" id="name">{{chart.name}}</td>
<td class="editable" id="slug">{{chart.slug}}</td>
<td>john#example.com</td>
</tr>
{% empty %}
<p>No data</p>
{% endfor %}
</tbody>
</table>
And this is my JavaScript code. I tried to try some methods myself but it didn't work
<script src="{% static 'npe_cp/js/bootstable.js' %}"></script>
<script>
//apply
$("#table-list").SetEditable();
$('#addRow').click(function() {
rowAddNew('table-list');
});
$('#bAcep').on('click', function(){
// var id=$("#id").val();
// var name=$("#name-44").val();
// var slug=$("#slug-44").val();
let name=document.querySelector('#name')
console.log(id, name, slug, 'Hello World')
$.ajax({
url:"/chart/edit",
type:"POST",
data:{
"id":id,
"name":name,
"slug":slug,
},
})
});
This is exactly what the table looks like. I want to update, create, and delete operations. But I am not getting the data.
Use Django Forms to populate the database, makes it easy to perform CRUD operations

How can I pass an ID from selected table row to my AJAX function that fetching data

Sorry to bother, I'm having a trouble passing and ID to my AJAX function.
I wanted to pass the ID of the selected table row to my AJAX function and use it for my query in my controller
this is the code for my table row
<div class="container">
<h2 style="margin-top: 12px;" class="alert alert-success">Details</h2><br>
<div class="row">
<div class="col-12">
<table class="table table-bordered" id="">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<td colspan="2">Action</td>
</tr>
</thead>
<tbody id="users-crud">
#foreach($merchants as $merchant)
<tr id="user_id_{{ $merchant->id }}">
<td>{{ $merchant->id}}</td>
<td>{{ $merchant->first_name }}</td>
<td>{{ $merchant->email }}</td>
<td><a id="getData" onClick="getData({{$merchant->id}})" class="btn btn-info">Show</a>
</td>
</tr>
#endforeach
</tbody>
</table>
{{ $merchants->links() }}
</div>
</div>
</div>
upon click show ID should pass it to my AJAX function,
this is the code of the script
<script type=text/javascript>
$(document).ready(function() {
});
function getData(id){
$('#myModal').modal('show');
$.ajax({ //create an ajax request to display.php
type: "GET",
url: "getproducts/",
// dataType: 'json',
data: {id: id}, // This will be {id: "1234"}
success: function (data) {
$("#id").html(data.id);
$("#first_name").text(data.first_name);
}
});
};
</script>
And ID will be use for my query in my controller, this is my controller's code, note that the number 1 in my where query is hard coded, I wanted to put the ID that I get from the selected table
public function getproducts()
{
$merchants = DB::table('merchants')
->select('merchants.*', 'product.product_name as product_names')
->join('product','product.id','=','merchants.id')
// THE NUMBER 1 IS HARD CODED
->where('merchants.id', 1)
->paginate(8);
return response()->json($test, 200);
}
Every method in a Laravel Controller can have arguments "injected" into them, including the Request $request variable. Add this to the top of your Controller after your namespace declaration:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
Then modify your method:
public function getproducts(Request $request) {
...
}
Then, instead of hard-coding the value 1, you pull it from your $request object:
->where('merchants.id', $request->input('id'))
The full documentation can be seen here:
https://laravel.com/docs/9.x/requests#accessing-the-request
Your code seems fine to me. What is the issue you are facing? But you can improve code by bit more.
<td><a id="getData" onClick="getData({{$merchant->id}})" class="btn btn-info">Show</a>
Instead you can use a global class. Also using same HTML id in a class is not good practice.
<td><a class="merchant_info" data-id="{{$merchant->id}}" class="btn btn-info">Show</a>
Now need modification to jQuery code
<script type=text/javascript>
$(document).ready(function() {
$('.merchant_info').click(function(e){
e.preventDefault();
var dataId = $(this).attr("data-id");
// Now do the Ajax Call etc
});
});
</script>

DataTables Refresh Django Ajax Data on CRUD Operations

I have a Django project with an Analytic model. This model is a list of analytics. It has a ForeignKeyField and a ManyToMany Field. The end goal is to have the user go to a URL where they can view a list of Analytics in a DataTable, create a new analytic, edit analytics, and delete analytics. Using this tutorial: https://simpleisbetterthancomplex.com/tutorial/2016/11/15/how-to-implement-a-crud-using-ajax-and-json.html, I accomplished all of these objectives in a regular Bootstrap HTML table (i.e. not in a DataTable).
When I attempted to introduce a DataTable to the mix, I discovered that my DataTable was pulling from the HTML/DOM source, so it was not updating unless the page was refreshed. So I then realized that I need to either configure the DataTable to initially pull from HTML/DOM and then pull from AJAX, or I need to initially use Ajax as the source.
It turns out, regular Django does not do a good job of serializing ManyToMany fields, so I opted to use DRF to serialize my Analytic model. This works to a degree: the JSON output looks decent, and the results show up in my DataTable. However, the data is still not updating when an Ajax call is made. In addition, DataTables does not really allow inline buttons for editing/deleting, which is why it was necessary to manually write those buttons into the HTML in the first place.
Question: How do I force a DataTable that is sourcing from HTML/DOM to update its data without refreshing the page when an Ajax CRUD operation is performed?
views.py:
def analytic_list(request):
analytics = Analytic.objects.all().select_related('analyticCategory').prefetch_related('dataSources')
return render(request, 'analytics/analytic_list.html', {'analytics':analytics})
def save_analytic_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
analytics = Analytic.objects.all()
data['html_analytic_list'] = render_to_string('analytics/includes/partial_analytic_list.html', {
'analytics': analytics
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def analytic_create(request):
if request.method == 'POST':
form = AnalyticForm(request.POST)
else:
form = AnalyticForm()
return save_analytic_form(request, form, 'analytics/includes/partial_analytic_create.html')
def analytic_update(request, pk):
analytic = get_object_or_404(Analytic, pk=pk)
if request.method == 'POST':
form = AnalyticForm(request.POST, instance=analytic)
else:
form = AnalyticForm(instance=analytic)
return save_analytic_form(request, form, 'analytics/includes/partial_analytic_update.html')
def analytic_delete(request, pk):
analytic = get_object_or_404(Analytic, pk=pk)
data = dict()
if request.method == 'POST':
analytic.delete()
data['form_is_valid'] = True # This is just to play along with the existing code
analytics = Analytic.objects.all()
data['html_analytic_list'] = render_to_string('analytics/includes/partial_analytic_list.html', {
'analytics': analytics
})
else:
context = {'analytic': analytic}
data['html_form'] = render_to_string('analytics/includes/partial_analytic_delete.html',
context,
request=request,
)
return JsonResponse(data)
urls.py:
url(r'^dataanalytics/analytics/$', views.analytic_list, name='analytic_list'),
url(r'^dataanalytics/analytics/create/$', views.analytic_create, name='analytic_create'),
url(r'^dataanalytics/analytics/(?P<pk>\d+)/update/$', views.analytic_update, name='analytic_update'),
url(r'^dataanalytics/analytics/(?P<pk>\d+)/delete/$', views.analytic_delete, name='analytic_delete'),
analytic_list.html:
{% block content %}
<!-- BUTTON TO TRIGGER THE ACTION -->
<p>
<button type="button"
class="btn btn-primary js-create-analytic"
data-url="{% url 'analytic_create' %}">
<span class="fa fa-plus"></span>
New analytic
</button>
</p>
<table class="table table-hover table-sm display responsive" width="100%" cellspacing="0" id="analytic-table">
<thead>
<tr>
<th class="all align-top">#</th>
<th class="all align-top">Name</th>
<th class="all align-top">Description</th>
<th class="all align-top">Category</th>
<th class="all align-top">Type</th>
<th class="all align-top">Format</th>
<th class="all align-top">Data Source(s)</th>
<th class="all align-top"></th>
<th class="none">Created By</th>
<th class="none">Created Date</th>
<th class="none">Modified By</th>
<th class="none">Modified Date</th>
</tr>
</thead>
<!-- <tbody>
{% include 'analytics/includes/partial_analytic_list.html' %}
</tbody> -->
</table>
<!-- THE MODAL WE WILL BE USING -->
<div class="modal fade" id="modal-analytic">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
{% endblock %}
partial_analytic_list.html:
{% for analytic in analytics %}
<tr>
<td>{{ analytic.id }}</td>
<td>{{ analytic.analytic }}</td>
<td>{{ analytic.analyticDescription }}</td>
<td>{{ analytic.analyticCategory }}</td>
<td>{{ analytic.analyticType }}</td>
<td>{{ analytic.analyticFormat }}</td>
<td>
{% for data_source in analytic.dataSources.all %}
{{ data_source }}
{% endfor %}
</td>
<td>
<button type="button"
class="btn btn-warning btn-sm js-update-analytic"
data-url="{% url 'analytic_update' analytic.id %}">
<span class="fa fa-pencil-alt"></span>
</button>
<button type="button"
class="btn btn-danger btn-sm js-delete-analytic"
data-url="{% url 'analytic_delete' analytic.id %}">
<span class="fa fa-trash-alt"></span>
</button>
</td>
<td>{{ analytic.createdBy }}</td>
<td>{{ analytic.createdDateTime }}</td>
<td>{{ analytic.modifiedBy }}</td>
<td>{{ analytic.modifiedDateTime }}</td>
</tr>
{% empty %}
<tr>
<td colspan="7" class="text-center bg-warning">No analytic</td>
</tr>
{% endfor %}
analytics.js:
$(function () {
/* Functions */
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-analytic").modal("show");
},
success: function (data) {
$("#modal-analytic .modal-content").html(data.html_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#analytic-table tbody").html(data.html_analytic_list);
$("#modal-analytic").modal("hide");
}
else {
$("#modal-analytic .modal-content").html(data.html_form);
}
}
});
return false;
};
/* Binding */
// Create analytic
$(".js-create-analytic").click(loadForm);
$("#modal-analytic").on("submit", ".js-analytic-create-form", saveForm);
// Update analytic
$("#analytic-table").on("click", ".js-update-analytic", loadForm);
$("#modal-analytic").on("submit", ".js-analytic-update-form", saveForm);
// Delete analytic
$("#analytic-table").on("click", ".js-delete-analytic", loadForm);
$("#modal-analytic").on("submit", ".js-analytic-delete-form", saveForm);
var table = $('#analytic-table').DataTable(
{
});
});
I'm going to assume you're talking about JQuery Datatables. You're SO close, just missing a few bits! You need to destroy and reinitialize the table, no need to use .draw(). Do as shown here:
Ajax:
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#modal-analytic").modal("hide"); //hide it first if you want
$("#analytic-table").DataTable().destroy(); //this will flush DT's cache
$("#analytic-table tbody").html(data.html_analytic_list); // replace the html
$("#analytic-table").DataTable(); // re-initialize the DataTable
}
else {
$("#modal-analytic .modal-content").html(data.html_form);
}
}
});
return false;
};
Nice work and good luck! Late answer, but maybe it will help somebody.
It looks like your table updates are using this:
$("#analytic-table tbody").html(data.html_analytic_list);
You will need to you Datatables APIs to update the Datatables data. Since you are directly updating the HTML Datatables is not aware of the updates. One option is to use something like rows().invalidate() to have Datatables update its data cache after you update with HTML methods.
However a better option is to use rows.add() for multiple rows or row.add() for a single row.
Since it looks like you have tr elements in your data then you can use something like this for one row or multiple rows, respectively:
table.row.add($(data.html_analytic_list)).get(1)).draw();
table.rows.add($(data.html_analytic_list))).draw();

Jquery datatables plugin for django

I am newbie to django. I am using jquery datatable plugins in my django application. These datatables are working fine for the small datasets sent from my view. I have a django model which is having 65k records with 5 columns. when I am trying to show these records in jquery datatables the rendered page becoming unresponsive for a moment and the page is loading correctly. Also sorting, searching, pagination features are working fine with reasonable to amount of time. I want to see the page responsive even when I am showing 65k entries in datatables. Is there any way to do this? or what will be the best solution to handle large datasets? Pls suggest me
I came to know that this is because I am trying to format datatables on client side after loading 65k records from the server. Also I googled n knew that server side processing will be the best way to handle this. Any one pls suggest me how to do server side processing in django.
Now, my code is as follows:
part of Inventory.html:
<div class="box-body table-responsive" id='postinfo'>
</div>
InventoryOutputAlldata.html:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
$(function(){
$('#example1').dataTable({
});
});
</script>
</head>
<table id="example1" class="table table-bordered table-hover">
<thead>
<tr>
<th>Device</th>
<th>Device Type</th>
<th>Mac Address</th>
<th>IP Address</th>
<th>Status</th>
</tr>
</thead>
<tbody >
<form name="trform" method="post">
{% for key,value in data.items %}
<tr class="trselected" onclick="trclick(this)">
<td>{{ value.0 }}</td>
<td>{{ value.1 }}</td>
<td>{{ value.2 }}</td>
<td>{{ value.3 }}</td>
<td>{{ value.4 }}</td>
</tr>
{% endfor %}
</form>
</tbody>
<tfoot>
<tr>
<th>Device</th>
<th>Device Type</th>
<th>Mac Address</th>
<th>IP Address</th>
<th>Status</th>
</tr>
</tfoot>
</table>
</html>
JS:
$(function(){
var data = new Object();
data['showdata'] = 'all';
data["csrfmiddlewaretoken"] = $("input[name='csrfmiddlewaretoken']").val();
$( "#postinfo" ).load( "/alldata/", data, function( response, status, xhr )
{
});
});
URLs.py:
urlpatterns = patterns('',
url(r'^inventory/$', TemplateView.as_view(template_name='inventory.html')),
url(r'^alldata/$', 'NetworkInventory.nmap_integration.alldata'),
)
views.py:
def alldata(request):
postedInfo = request.POST
count = 0
dataDict = {}
dbData = nmap.objects.all()
if 'showdata' in postedInfo and postedInfo['showdata'] == 'all':
for data in dbData:
count += 1
dataDict[count] = []
dataDict[count].append(data.device)
dataDict[count].append(data.devicetype)
dataDict[count].append(data.macaddress)
dataDict[count].append(data.ipaddress)
dataDict[count].append(data.status)
else:
return HttpResponse('Improper Behaviour')
return render_to_response('inventoryOutputAlldata.html',{'data': dataDict})
Please suggest me how can i modify this to work with large datasets.
When you do it that way all of the records are loaded into cache. You need to use iterate.
Perhaps this is what you want.
car_set = Car.objects.all()
for car in car_set.iterator():
#Do something
Or more advanced
djangosnippets
Try this
import gc
def queryset_iterator(queryset, chunksize=1000):
'''''
Iterate over a Django Queryset ordered by the primary key
This method loads a maximum of chunksize (default: 1000) rows in it's
memory at the same time while django normally would load all rows in it's
memory. Using the iterator() method only causes it to not preload all the
classes.
Note that the implementation of the iterator does not support ordered query sets.
'''
pk = 0
last_pk = queryset.order_by('-pk')[0].pk
queryset = queryset.order_by('pk')
while pk < last_pk:
for row in queryset.filter(pk__gt=pk)[:chunksize]:
pk = row.pk
yield row
gc.collect()
You can simply use a page loader for this. You can set the page loader to the time taken for your datatable rendered correctly into the page.

jQuery form selector doesnt seem to work

I am trying to put a generic form submit function.
For some reason the form submit action is not being captured at all by jQuery.
I am using the following:
$('form').submit(function( event ) {
alert("Form submit through ajax");
event.preventDefault();
});
I never get the alert and the form goes for a normal post submission which invariably fails as the back-end is a python django class based view that is specifically handling the ajax requests. I am new to jQuery.
$(document).ready(function(){
$.ajaxSetup(
{type:'POST'});
$('.nav_menu').click(function(){
var hostname = window.location.origin;
alert("hostname = " + hostname + $(this).attr("id"));
$.ajax({
type: 'GET',
url: hostname + $(this).attr("id"),
data: {},
success: function(data){
var page = data['page'];
$('#view_area').empty();
$('#view_area').append(page);
}
});
});
/*$('form').submit(function(){
alert("Form submit in ajax");
//$(this).ajaxSubmit();
return false;
});*/
$('form').submit(function( event ) {
event.preventDefault(); // <-- important
alert("Form submit through ajax");
/*$(this).ajaxSubmit({
target: '#output'
});*/
});
$(':submit').click(function(){
alert(":submit = Form submit through AJax");
});
});
That is the full jQuery file.
The following is my html from where the form is present.
<table>
<thead>
<tr>
<th></th>
<th>ID</th>
<th>Name</th>
<th>D.O.B</th>
<th>Marital Status</th>
<th>Mobile</th>
<th>Alt Mobile</th>
<th>Alt Contact</th>
<th>Office Number</th>
<th>Primary Address</th>
<th>Permanent Address</th>
<th>Secondary Address</th>
</tr>
</thead>
<tbody>
{% for e in entry_all %}
<tr><th><form action="" method="post">{% csrf_token %}
<label for="id_emp_id"></label> <input id="id_emp_id" maxlength="50" name="emp_id" type="hidden" value="{{ e.emp_id }}" />
<input type="submit" value="Remove">
</form>
</th>
<th>{{ e.emp_id }}</th>
<td>{{ e.name }}</td>
<td>{{ e.dob }}</td>
<td>{{ e.marital_stat }}</td>
<td>{{ e.cell_no }}</td>
<td>{{ e.cell2_no }}</td>
<td>{{ e.alt_no }}</td>
<td>{{ e.off_ll }}</td>
<td>{{ e.prim_addr }}</td>
<td>{{ e.perm_addr }}</td>
<td>{{ e.sec_addr }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr/>
I was originally using a cdn to load a jquery. For some reason this is not working all the time for me. So I decided to serve it statically. Strangely, cdn links have no issue on my team mates system. No code change.
EDITED
Code below should work as expected.
In jQuery, there's a preventDefault method which you can call to prevent the default action of an event. For forms, the default action is to either "GET" or "POST" data to or from the script or page provided in the form's action parameter.
If you want to prevent the default action of your form (stop it from submitting and following the action url), you need to call preventDefault first and foremost somewhere in your handler code.
Here's an example:
$("#myform").on("submit", function(e) {
e.preventDefault();
alert("Now I can run...");
// do AJAX call
$.ajax({
type : "POST",
url : "your-script.py",
data : { foo : "bar" }
})
.done(function(results) {
// done with post
// parse data returned from Python
// available in results parameter
});
});
If your handler is not running at all, you're likely not referencing your form correctly.

Categories

Resources