Django pass data from HTML table to database model - html

I am creating a student attendance system using django. I am fetching all student's names from the student database into an HTML table and updating information about students to django model.
This is my view.py to get data
def attendanceFill (request, subject):
context = ''
ad_standard = request.session.get('standardO')
subjects = CustomStudent.objects.filter(className__name__contains = ad_standard, subjectName__subjects__contains = subject)
# attendanceForm = Attendance(request.POST or None, instance=subjects)
print(ad_standard)
print(subject)
print(subjects)
context = {'subjects' : subjects}
if request.method == 'POST':
student = request.POST
print(student)
return render(request, 'teacher/attendance_fill.html', context)
This is my HTML template for data handling.
<div class="container">
<div class= "row mt-4">
<form action="" method="POST">
{% csrf_token %}
<table>
{% for student in subjects %}
<tr>
<td name= 'student'><p class="student-name" id="student-name">{{ student.sname }}</p></td>
<td>
<input type="checkbox" name="attendance" id="attendance">
</td>
</tr>
{% endfor %}
<tr>
<td>
<button type="button" name="checked" id = "checked" class="btn btn-outline-dark mb-4 shadow" style="border-radius:25px;">Submit</button>
</td>
<td></td>
</tr>
</table>
</form>
</div>
</div>
This is jquery function I am using to capture data.
var formData = new FormData()
$(document).ready(function(){
$("#checked").click('click', function(){
$students = document.getElementsByClassName('student-name').textContent;
$attendance = $('#attendance').val()
console.log($students)
console.log($attendance)
})
})
I have tried $('student-name').val() to get value for all students but it returns blank. Nothing is captured with this method.
I wish capture all data and update it into attendance model.
This are my models:
# Custom Student Table
class CustomStudent(models.Model):
_id = models.AutoField
sname = models.CharField(max_length = 50)
slname = models.CharField(max_length = 50)
admissionNo = models.CharField(default= "", max_length=50)
parentName = models.CharField(default= "", max_length=100)
emerContact = models.CharField(default= "", max_length=50)
contactNo = models.CharField(default= "", max_length=50)
className = models.ForeignKey(Standard, on_delete=models.DO_NOTHING)
subjectName = models.ManyToManyField(Subject)
Year = models.CharField(default="", max_length=5)
email = models.CharField(default="", max_length=60)
address = models.CharField(default="", max_length=250)
def __str__(self):
# return str(self.slname)
return str(self.sname)
AttendenceChioces = [
('Y', 'Yes'),
('N', 'No')
]
# Student Attendance Table
cla
AttendanceStudent(models.Model):
attendace_id = models.AutoField(primary_key= True)
student = models.ForeignKey(CustomStudent, on_delete=CASCADE)
attendace = models.CharField(max_length = 50, choices=AttendenceChioces)
date = models.DateField(auto_now= True)
teacher = models.CharField(max_length=255)
def __str__(self):
return str(self.sname)
Is there any other efficient way to submit attendance data into database. I have tried capturing all data using jquery but it returns blank.
UPDATE:
I have figured out proper way to send data but issue is django is not receiving any data in view funtion. I have created a view function to process data as my current view function attendancefill cannot process url without subject value.
def attendanceFilled(request):
print(request.POST)
if request.method == 'POST':
print (request.POST)
return JsonResponse({'data' : request.POST}, status=200)
return render(request, 'teacher/attendance_st.html')
I have verified via console.log and chrome DevTools tat ajax is sending data. But in django there is no data. I have tried printing new data at all points in new view function. It always returns a empty dict.
This is my updated jquery:
var value = []
$(document).ready(function(){
$("#checked").click('click', function(){
csrf = $("input[name=csrfmiddlewaretoken]").val();
value.push({'csrfmiddlewaretoken' : '{{ csrf_token }}'})
$('#attendance_table tr').each(function(a,b){
$student = $('.student-name', b).text();
$present = $('#attendance', b).prop('checked');
value.push({Student : $student, Present : $present})
})
var datatoadd = JSON.stringify(value);
document.getElementById("demo").innerHTML = datatoadd;
console.log(datatoadd)
$.ajax({
type: "POST",
url: '{% url "attendanceFilled" %}',
data: datatoadd,
cache: false,
processData: false,
contentType: false,
success: function(){
alert('Attendance submitted')
},
error: function(xhr, errmsg, err){
console.log(xhr.status + ":" + xhr.responseText)
alert('Attendance Failed to Submit! Please contact adminitstrator with your issue!')
}
})
})
})
my path in urls:
path('subject/<slug:subject>/', views.attendanceFill, name="subject"),
path('attendanceFilled', views.attendanceFilled, name="attendanceFilled"),
I am only posting required URLs here my URL file is too big.

#Sahil Mohile- Your model needs some clean-up.
class StudentAttendance(models.Model):
attendance_id = models.AutoField(primary_key= True)
student = models.ForeignKey(CustomStudent, on_delete=CASCADE,db_index=True)
attendace = models.CharField(max_length = 20, choices=AttendenceChioces)
date = models.DateField(auto_now= True)
teacher = models.ForeignKey(settings.AUTH_USER_MODEL)#Dont call it #tname, explicit is better than implicit.
def __str__(self):
return str(self.sname)
Now. my main point. Attendance record is tied to a Term/Semester. How about you
create a Semester Table. Tie the student attendance with a specific semester/term
import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Semester(models.Model):
name = models.CharField(max_length=50)
year = models.PositiveIntegerField(
default=current_year(), validators=[MinValueValidator(1984), max_value_current_year])
.........
e.g Fall 2020
class StudentAttendance(models.Model):
attendance_id = models.AutoField(primary_key= True)
semester = models.ForeignKey(Semester,db_index=True)
student = models.ForeignKey(CustomStudent, on_delete=CASCADE,db_index=True)
attendace = models.CharField(max_length = 20, choices=AttendenceChioces)
date = models.DateField(auto_now= True)
teacher = models.ForeignKey(settings.AUTH_USER_MODEL)#Dont call it #tname, explicit is better than implicit.
Also, I predict that there might be a situation where you will be asked to present the number of present days for a specific student in a specific semester. Something to think about.
I am a bit confused. You are capturing the data but where are you making the ajax POST? You need to share the POST request
var formData = new FormData()
$(document).ready(function(){
$("#checked").click('click', function(){
$students = document.getElementsByClassName('student-name').textContent;
$attendance = $('#attendance').val()
console.log($students)
console.log($attendance)
})
})
Shouldn't you be doing the following too
$.ajax({
type: "POST",
url: 'your url',
data: {
#your data
csrfmiddlewaretoken: csrf_token
},
success:function(response){
},
error:function(error){
}
});

Related

How to assign ForeignKey MySQL item in views.py?

When I save my NoteForm, I want to save my form and the "note" field, then I want to create a "tag" for the Note in the NoteTagModel.
At the moment, I create a new tag but it is not assigned to the note. I know that the following code must be wrong:
notetag.id = new_note_parse.id
If I change to:
notetag.note = new_note_parse.id
I receive the following error:
"NoteTagModel.note" must be a "NoteModel" instance.
The below is my views.py:
def notes(request):
note_form = NoteForm
notetag = NoteTagModel()
note_form=NoteForm(request.POST)
if note_form.is_valid():
new_note = note_form.save(commit=False)
new_note_parse = new_note
new_note.save()
notetag.id = new_note_parse.id
notetag.tag = "Test"
notetag.save()
return HttpResponseRedirect(reverse('notes:notes'))
context = {
'note_form' : note_form,
'notes' : NoteModel.objects.all(),
'notes_tag' : NoteTagModel.objects.all(),
}
return render(request, "notes/notes.html", context)
My models.py is:
class NoteModel(models.Model):
note = models.CharField(
max_length = 5000
)
def __str__(self):
return f"{self.note}"
class NoteTagModel(models.Model):
note = models.ForeignKey(
NoteModel,
on_delete=models.CASCADE,
related_name="notes",
blank= False,
null = True,
)
tag = models.CharField(
max_length = 5000
)
def __str__(self):
return f"Note: {self.note} | Tag: {self.tag}"
I have the following as my forms.py:
class NoteForm(ModelForm):
class Meta:
model = NoteModel
fields = [
'note',
]
Change views.py to reflect the below:
note = NoteModel.objects.get(id=new_note_parse.id)
notetag.note = note

How to Pass an Image File to a API Endpoint

I have a web services with DRF, I have POSTMAN passing the right all fields right with success including the image file ['avatar']
[]1
Now how do i pass the image file from a Django Form, but i keep getting Error 400, Bad request. Please how do i encode the image file to be passed into the API endpoint .
html
<form method="post" action="#" enctype="multipart/form-data">
{% csrf_token %}
<label for="phone">Enter Phone</label>
{{ form.phone }} <br />
<label for="bvn">Enter BVN</label>
{{ form.bvn }} <br />
<label for="avatar">Upload Avatar</label>
{{ form.avatar }} <br />
<button type="submit" class="btn btn-primary" >Submit</button>
</form>
views.py
def form_valid(self, form):
token = self.request.session['session_token']
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
parameters = {
'bvn': form.cleaned_data['bvn'],
'phone': form.cleaned_data['phone'],
'avatar': self.request.FILES['avatar']
}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_api/'), data=parameters,
headers=headers)
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, 'Successfully updated profile')
else:
messages.error(self.request, 'API Error %s' % response.status_code)
return super(CustomerDashboard, self).form_valid(form)
form.py
class ProfileUpdateForm(forms.Form):
"""customer profile update form"""
phone = forms.CharField(required=False, widget=NumberInput(attrs={'class': 'form-control',
'type': 'number', 'id': 'phone',
'placeholder': 'Enter Phone Number'}))
bvn = forms.CharField(required=False, widget=NumberInput(attrs={'class': 'form-control',
'type': 'number', 'id': 'bvn',
'placeholder': 'Enter BVN'}))
avatar = forms.ImageField(required=False, widget=ClearableFileInput(attrs={'class': 'form-control',
'type': 'file', 'id': 'avatar',
'placeholder': 'Upload Avatar'}))
Yours headers is wrong.
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
change to:
headers = {"Content-Type": 'multipart/form-data', "Authorization": "Token " + token}
When you upload some file you should use multipart/form-data instead of application/json
(If you certainly do not send the file as base64)
Should someone else run into the same issue, The only way i was able to solve it is to have separate views to handle image and other text fields. What i did so far that worked.
If you noticed, the content-type header for the view that handles the image wasnt inserted, Just remove it and let it your API handle it by itself, several times i set it as multipart/form-data, i will hit response code 200/201, but file never get saved.
my API views.py
class CustomerApiView(generics.UpdateAPIView, generics.ListAPIView):
"""Customer Api View to update customer profile"""
http_method_names = ['put', 'get']
renderer_classes = [renderers.JSONRenderer]
authentication_classes = [authentication.TokenAuthentication]
serializer_class = CustomerSerializer
queryset = Profile.objects.all()
permission_classes = [IsAuthenticated]
def get_queryset(self):
user = self.request.user
return self.queryset.filter(user=user)
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
# make sure to catch 404's below
obj = queryset.get(user_id=self.request.user.id)
self.check_object_permissions(self.request, obj)
return obj
class CustomerAvatarApiView(generics.UpdateAPIView):
"""Customer Avatar/DP API View"""
serializer_class = CustomerAvatarSerializer
queryset = Profile.objects.all()
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [IsAuthenticated]
renderer_classes = [renderers.JSONRenderer]
http_method_names = ['put', 'get']
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
# make sure to catch 404's below
obj = queryset.get(user_id=self.request.user.id)
self.check_object_permissions(self.request, obj)
return obj
serializer.py
class CustomerSerializer(serializers.ModelSerializer):
"""Customer Profile Serializer"""
class Meta:
"""Class Meta"""
model = Profile
fields = ('pk', 'phone', 'bvn', 'avatar')
extra_kwargs = {'pk': {'read_only': True}, }
class CustomerAvatarSerializer(serializers.ModelSerializer):
"""Separate Serializer to handle upload of file"""
class Meta:
"""Class Meta"""
model = Profile
fields = ('avatar', )
my view.py
class CustomerDashboard(LoginRequiredMixin, generic.FormView):
"""customer dashboard view"""
template_name = 'customer/dashboard.html'
form_class = ProfileUpdateForm
raise_exception = False
success_url = reverse_lazy('customer_dashboard')
def get_profile_api(self):
"""get profile api call to fetch profile; passing in the token from session"""
token = self.request.session['session_token']
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
response = requests.get(str(settings.API_END_POINT + '/customer_profile_api/'), headers=headers)
json_response = response.json()
return json_response
def get_initial(self):
initial = ''
try:
initial = super(CustomerDashboard, self).get_initial()
initial['phone'] = self.get_profile_api()[0]['phone']
initial['bvn'] = self.get_profile_api()[0]['bvn']
except:
pass
return initial
def get_context_data(self, **kwargs):
"""overriding get_context_data to pass data to template"""
context = super(CustomerDashboard, self).get_context_data()
if self.get_profile_api()[0]['bvn'] != '': # if BVN has been filled before pass True or False to template
context['bvn_initial'] = True # Todo Validate BVN from API Before calling save method on it
else:
context['bvn_initial'] = False
return context
def form_valid(self, form):
token = self.request.session['session_token']
if 'updateAvatar' in self.request.POST:
headers = {"Authorization": "Token " + token}
avatar = form.cleaned_data['avatar']
file = {'avatar': (str(avatar), avatar)}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_avi_api/'), files=file,
headers=headers)
message = 'Avatar changes successfully'
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, message)
else:
messages.error(self.request, 'API Error %s' % response)
elif 'updateProfile' in self.request.POST:
headers = {"Content-Type": "application/json", "Authorization": "Token " + token}
parameters = {
'bvn': form.cleaned_data['bvn'],
'phone': form.cleaned_data['phone'],
}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_api/'), json=parameters,
headers=headers)
message = 'Profile changes successfully'
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, message)
else:
messages.error(self.request, 'API Error %s' % response)
return super(CustomerDashboard, self).form_valid(form)

How to receive and save data via ajax in django?

through ajax I am sending the data correctly, because the data I see through wireshak and they are correct. On the django server, he sends me the correct request "POST / solit / HTTP / 1.1" 200 52. But the value sent does not receive it, it does not reach the Mysql database and I do not understand why, if the traffic sends well the data.
In wireshak I see the data of the post request, they are the correct ones, but they are not saved in the database, when I want them to be added as if I were to update the record of such database fields and it does not , I do not understand why
this is my views.py
def solit(request):
if request.method == 'POST' and request.is_ajax():
form = addiForm(request.POST)
if form.is_valid():
peticion = form.save(commit=False)
peticion.usuario = request.user
peticion.save()
peticion.usuario.d_pendientes = form.cleaned_data.POST.get('d_pendientes')
peticion.usuario.h_pendientes = form.cleaned_data.POST.get('h_pendientes')
peticion.usuario.save()
return JsonResponse({'status': 'true', 'msg': 'Procesado Correctamente'})
form = addiForm()
return render(request, 'plantillas/adicionar.html', {'form':form})
This is my models.py------------------------------
class Usuarios(AbstractUser):
numero_empleado = models.IntegerField(null= True, blank= True)
area = models.CharField(max_length = 200, null= True, blank= True)
d_pendientes = models.IntegerField(null= True, blank= False)
h_pendientes = models.IntegerField(null= True, blank= False)
f_init = models.DateField(max_length = 200,null= True, blank= True)
init_vac = models.DateField(max_length = 200, null= True, blank= True)
fin_vac = models.DateField(max_length = 200, null= True, blank= True)
ul_vac_tomadas = models.IntegerField(null= True, blank= True)
class Peticion(models.Model):
solit_choices = (
('Adicionar','Adicionar'),
)
solicitudes_id = models.AutoField(primary_key=True)
usuario = models.ForeignKey(Usuarios, on_delete=models.CASCADE, null=True, blank=True)
petit = models.CharField(max_length = 255, choices=solit_choices, null=True, blank=False)
fec = models.DateTimeField(auto_now=True)
razon = models.TextField(max_length=255, null=True, blank=True)
periodo_init = models.DateField(max_length = 200, null=True, blank=True)
periodo_fin = models.DateField(max_length = 200, null=True, blank=True)
dias_adicion = models.IntegerField(null=True, blank=False)
horas_adicion = models.FloatField(null=True, blank=False)
this is my forms.py
class addiForm(forms.ModelForm):
class Meta:
"""Formulario de solicitud"""
model = Peticion
fields = [
'solicitudes_id',
'petit',
'razon',
'periodo_init',
'periodo_fin',
'dias_adicion',
'horas_adicion',
]
labels = {
'solicitud_id':'Solicitud',
'petit':'Tipo de PeticiĆ³n',
'razon':'Razon',
'periodo_init':'Rango de fecha inicial',
'periodo_fin':'Fecha final',
'dias_adicion':'Dias a adicionar, si es mas de 8 horas',
'horas_adicion':'Horas a adiciona, si es menos de 1 dia',
html file
{% extends "plantillas/base.html" %}
{% block content %}
{% load staticfiles %}
{% now "Y-m-d H:i:s" %} <br>
{{ user.Peti}}
{{ user.numero_empleado}}
<script src="{% static 'js/int.js'%}"></script>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<div><form method="POST" id="demo" class="form-data" action="{% url 'solit' %}">
{% csrf_token %}
<h6>Tipo de peticion:{{form.petit}}</h6>
<h6>Razon:{{form.razon}}</h6>
<h6>{{form.solicitudes_id}}</h6>
<h6>Fecha inicio:{{form.periodo_init}}</h6>
<h6>Fecha fin:{{form.periodo_fin}}</h6>
<h6>Introduzca dias a tomar<input id="dias" type="number" name="dias_adicion"></h6>
<h6>Introduzca horas a tomar<input id="horas" type="number" name="horas_adicion"></h6>
<input type="hidden" id="const_dias" name="d_pendientes" value="{{ user.d_pendientes }}">
<input type="hidden" id="const_horas" name="h_pendientes" value="{{ user.h_pendientes }}">
<button type="submit" onclick="calculo()">Guardar</button>
</div></form></span>
<h6>Recuerde, que usted dispone de {{ user.d_pendientes }} dias y {{ user.h_pendientes }} horas</h6>
js file---------------------
function calculo()
{
var dias = parseInt(document.getElementById('dias').value);
var horas = parseFloat(document.getElementById('horas').value);
var dias_base = parseInt(document.getElementById('const_dias').value);
var horas_base = parseFloat(document.getElementById('const_horas').value);
dias_base -= dias;
horas_base -= horas;
document.getElementById('const_dias').value = dias_base;
document.getElementById('const_horas').value = horas_base;
} console.log(calculo);
server django console [24/Jul/2019 15:30:47] "POST /solit/ HTTP/1.1" 200 52 and the js console msg: "Procesado Correctamente"
status: "true"
ajax script--------------------------------------------
$(document).ready(function(calculo){
var productForm = $("#demo")
productForm.submit(function(event){
event.preventDefault();
var thisForm = $(this)
var actionEndpoint = thisForm.attr("action");
var httpMethod = thisForm.attr("method");
var formData = thisForm.serialize();
$.ajax({
url: actionEndpoint,
method: httpMethod,
data: formData,
success: function(data){
console.log("success")
console.log(data)
},
error: function(erroData){
console.log("error")
console.log(erroData)
}
})
})
})
You still haven't really explained where you want the value for "usario" to come from. I'm going to assume that you want it to be the currently logged-in user. In which case, you can do this:
form = addiForm(request.POST)
if form.is_valid():
peticion = form.save(commit=False)
peticion.usuario = request.user
peticion.save()
peticion.usuario.d_pendientes = form.cleaned_data.get('d_pendientes')
peticion.usuario.h_pendientes = form.cleaned_data.get('h_pendientes')
peticion.usuario.save()
return JsonResponse({'status': 'true', 'msg': 'Procesado Correctamente'})
(Note, .get is a method, it needs parentheses not square brackets. And None is the default, you don't need to specify it explicitly.)
Edit
I'm finding it really hard to understand what you are asking, but I think your problem is that you simply don't have anything in the form called dias_adicionar or horas_adicionar; they are called d_pendientes and h_pendientes in line with your actual field names.
There isn't anything in your JavaScript code which makes an AJAX request - it's just a normal form POST request. This means request.is_ajax() will be false, and the form saving code doesn't execute.

Easiest way to update model values using Django with an AJAX form

I have a django model which contains some fields with associated choices:
class Product(models.Model):
CONDITION_CHOICES = (
("GOOD", "Good"),
("BAD", "Bad"),
("UNKNOWN", "Unknown"),
)
name = models.CharField(max_length=200, blank=True, null=True)
colour = models.CharField(max_length=200, blank=True, null=True)
condition = models.CharField(max_length=20, choices=CONDITION_CHOICES, blank=True, null=True)
condition_source = models.CharField(max_length=20, blank=True, null=True)
condition_last_updated = models.DateTimeField(blank=True, null=True)
I also have a bootstrap driven form that looks like:
<div class="form-group">
<label class="control-label"><strong>Condition</strong></label>
<br/>
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-outline-primary">
<input type="radio" name="condition" value="GOOD" autocomplete="off">
Good
</label>
<label class="btn btn-outline-primary">
<input type="radio" name="condition" value="BAD" autocomplete="off">
Bad
</label>
<label class="btn btn-outline-primary">
<input type="radio" name="condition" value="UNKNOWN" autocomplete="off">
Unknown
</label>
</div>
</div>
I am trying to make it so that when a user clicks on one of the buttons in the UI, the Product model is updated (specifically the condition, condition_source and condition_last_updated fields). The actual model has multiple fields with associated with choice options so I'd like the model to get updated in real time without a page reload as a user works through the form.
Any guidance would be appreciated here - I have looked at intercooler.js but unsure if this is the right tool for the job.
As you have not specified what condition_source should include I have set it to string some_source
Ajax:
$('.btn').on('click', function(){
$.post(
'/your_vew/',
{
'source': "some_source",
'condition': $(this).find('input').val(),
'csrfmiddlewaretoken': '{{csrf_token}}'
},
function(data){
console.log(data.response);
}
);
});
urls.py:
urlpatterns = [
...
path('your_vew/', views.your_view),
...
]
views.py:
from django.http import JsonResponse
from datetime import datetime
def your_view(request):
data = {'response': ''}
if request.method == 'POST':
p1 = Product.objects.filter(pk=1).update(
condition_source=request.POST.get('source'),
condition=request.POST.get('condition'),
condition_last_updated=datetime.now()
)
if p1:
data['response'] = 'Record updated!'
return JsonResponse(data)
Now, you have a few options. What I did is that i used the Jquery ajax method in form of a class and set up my functions for my applications inside this class. Django requires the csrf token in order to process incomming requests. So i found these two functions which retreives the cookie csrf token from the client.
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
Once the csrf token has been stored in a variable you need to pass this to the ajax beforeSend function for example like this:
ajax_setup(enable_async){
enable_async = true;
$.ajaxSetup({
async: enable_async,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
}
}
The full ajax request would be something like
update_user_language(user_id, lang, callback){
this.ajax_setup(true);
$.ajax({
url: this.url,
type: "POST",
data: {
'user_id':user_id,
'lang':lang,
},
dataType: 'json',
success: function(data){
db_request_after();
if(callback !== undefined) callback(data);
},
error: function(){
db_request_error();
},
});
}
Note the callback variable. This allows ajax to call a function passing the data retreived from the webservice.
Once you sent the request you need to setup your view.py to accept the request and process the POST variables.
def sample_view(request):
if request.method == "POST"
user_id = request.POST.get('user_id')
lang = request.POST.get('lang')
#update the model value
user = User.objects.get(pk=user_id)
user.language = lang
user.save()
return JsonResponse({'message':'user updated'})
else:
return render(...)

Why CRUD Operations Using Ajax and Json for Django powered app is so slow?If being 7000 records is an issue, how can I improve it to seconds?

I am performing operations on remote legacy MySQL database having about 7000 records.Currently, it's taking around 1.5 minutes for the Update / Delete / Create operation.I have also imported necessary files which is not included in Views.py below.
Is using dict() a problem? Should I use Rest? OR some other API. Any suggestions will be appreciated!
Here is the code:
plugin.js
$(document).ready(function(){
var ShowForm = function(){
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType:'json',
beforeSend: function(){
$('#modal-book').modal('show');
},
success: function(data){
$('#modal-book .modal-content').html(data.html_form);
}
});
};
var SaveForm = function(){
var form = $(this);
$.ajax({
url: form.attr('data-url'),
data: form.serialize(),
type: form.attr('method'),
dataType: 'json',
success: function(data){
if(data.form_is_valid){
$('#book-table tbody').html(data.book_list);
$('#modal-book').modal('hide');
} else {
$('#modal-book .modal-content').html(data.html_form)
}
}
})
return false;
}
// create
$(".show-form").click(ShowForm);
$("#modal-book").on("submit",".create-form",SaveForm);
//update
$('#book-table').on("click",".show-form-update",ShowForm);
$('#modal-book').on("submit",".update-form",SaveForm)
//delete
$('#book-table').on("click",".show-form-delete",ShowForm);
$('#modal-book').on("submit",".delete-form",SaveForm)
});
Views.py
# Fetching records with pagination
#login_required()
def book_list(request):
books = AvailstaticCopy.objects.all().order_by('-row_date')
page = request.GET.get('page', 1)
paginator = Paginator(books, 144)
try:
books = paginator.page(page)
except PageNotAnInteger:
books = paginator.page(1)
except EmptyPage:
books = paginator.page(paginator.num_pages)
context = {
'books': books
}
return render(request, 'books/book_list.html',context)
#login_required()
def save_all(request,form,template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
books = AvailstaticCopy.objects.all()
data['book_list'] = render_to_string('books/book_list_2.html',
{'books':books})
else:
data['form_is_valid'] = False
context = {
'form':form
}
data['html_form'] = render_to_string(template_name,context,request=request)
return JsonResponse(data)
# Create new record
#login_required()
def book_create(request):
if request.method == 'POST':
form = AvailForm(request.POST)
else:
form = AvailForm()
return save_all(request,form,'books/book_create.html')
# Update record
#login_required()
def book_update(request,id):
book = get_object_or_404(AvailstaticCopy,id=id)
if request.method == 'POST':
form = AvailForm(request.POST,instance=book)
else:
form = AvailForm(instance=book)
return save_all(request,form,'books/book_update.html')
# Delete Record
#login_required()
def book_delete(request,id):
data = dict()
book = get_object_or_404(AvailstaticCopy,id=id)
if request.method == "POST":
book.delete()
data['form_is_valid'] = True
books = AvailstaticCopy.objects.all()
data['book_list'] = render_to_string('books/book_list_2.html',
{'books':books})
else:
context = {'book':book}
data['html_form'] =
render_to_string('books/book_delete.html',context,request=request)
return JsonResponse(data)
I suppose, your problem is in server responses. In all views where you change server data (delete, update, create) you try return updated book list, but you do not paginate book queryset, and django template processor take a lot of time to prepare html with all books. I suggest you add function which will paginate queryset like this:
def get_book_page(request, books):
page = request.GET.get('page', 1)
paginator = Paginator(books, 144)
try:
books = paginator.page(page)
except PageNotAnInteger:
books = paginator.page(1)
except EmptyPage:
books = paginator.page(paginator.num_pages)
return books
And wrap all book querysets in your views. Also it will be needed add to urls page number as get parameter (for example /update-book/1?page=2) because if you don't do it, it won't be work.
Thanks for giving me a hint.That worked! I have paginated queryset like this:
def save_all(request,form,template_name):
data = dict()
paginate_by = 144
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
books = AvailstaticCopy.objects.all().order_by('-row_date')
page = request.GET.get('page', 1)
paginator = Paginator(books, 144)
try:
books = paginator.page(page)
except PageNotAnInteger:
books = paginator.page(1)
except EmptyPage:
books = paginator.page(paginator.num_pages)
data['book_list'] = render_to_string('books/book_list_2.html',
{'books':books})
else:
data['form_is_valid'] = False
context = {
'form':form
}
data['html_form'] = render_to_string(template_name,context,request=request)
return JsonResponse(data)