Django Ajax success send context in new url - javascript

I have a first page with a Launch button, the process is done and them all is redirect to a result page where I can download the different results. Without Ajax and with "regular" Django, the process is working. However, because of other functionalities in the first page, I have to work with Ajax. And if I do not redifined the success part of Ajax, nothing is appenning..
I have a function view for the first page :
def launchCtd(request):
"""
This Function is activate when user click on the launch button of the convertToDose page.
It receive the request, create the JSON file and launch the ConvertToDose Analysis. Then it redirect to the Result page
"""
if request.method == 'POST':
#DO stuff
context = {
'filename': img_out_path,
'protocol_file': json_pactrlRectth,
}
#return render(request, 'result.html', context)
return JsonResponse(context, safe=False)# I trie to pass the url but it was not a success...
else:
#Ini Forms
context = {
#Send Forms
}
return render(request, 'template.html', context)
the template of the first page (only ajax part)
$.ajax({
url: "",
type: "POST",
data: formData,
processData: false,
contentType: false,
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
success: function(data){
//print okay with JSONResponse in view
console.log(data.protocol_file)
//First try to send data in new url => undefined element, after = I tried with data and with template data in the 1st page
//protocol_file = $("input[name='json_path']")
//filename = $("input[name='img_path']")
//Second try to send data in new url => undefined
$('#protocol_file').html(data.protocol_file);
$('#filename').html(data.filename);
//Third try => GetElementById is undifined error
//document.GetElementById("protocol_file").innerHTML = $("input[name='json_path']")
//document.GetElementById("filename").innerHTML = $("input[name='img_path']")
//Fourth try => synthaxe error, I also tried with a + like in some forum but it consider like a str and concat all...
window.location.href="/filmchromique/result/" {data:data}
#this one is working but with no data sended ....
//window.location.href="/filmchromique/result/"
},
error: function (data, textStatus, jqXHR) {
console.log(data)
}
});
The view of the result page :
class displayResultPage(TemplateView):
template_name = 'result.html'
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
kwargs = super(displayResultPage, self).get_context_data(**kwargs)
return kwargs
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
bar = self.request.POST.get('foo', None)
if bar: self.template_name = 'result.html'
return self.render_to_response(context)
In my template result, I have nothing particular, only maybe these part could be interesting :
<div style="padding-bottom: 30%" class="row gx-5 justify-content-center">
{% if protocol_file is not null %}
<p id="protocol_file">Your file is here : {{ filename }}</p>
{% else %}
<h1 style="color: indianred">You must launch an analysis before accessing an image on this page</h1>
{% endif %}
{% if protocol_file is not null %}
<div class="row gx-5 justify-content-center">
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' protocol_file %}">Save protocol to local</a>
</div>
<br>
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' filename %}">Save image to local</a>
</div>
<br>
</div>
I do not find a way to send the context. If you have any idea how I can do it please
Have a good day
EDIT
The problem seems not to be in the Ajax side but in the result view, here named displayResultPage. I used the debugger, and in the second post def, data are in the request (POST). So I had the idea to add them in the current context :
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
context["filename"] = self.request.POST.get("img_path")
context["protocol_file"] = self.request.POST.get("json_path")...
But the data are not displayed in the template.
When I use the debbugger, following the workflow :
the post function is called -> self.get_context_data called in the
post function -> return self.render_to_response of the post function
-> something done in class TemplateView -> come back in the get_context_data of displayResultPage -> something done in class
TemplatView -> page displayed
in the "come back in the get_context_data of displayResultPage" step, I do not find my data given to the context in the "the post function is called" step.
If you have any idea why, I think it is the solution here :) If I find a way I will post it.
Thanks

Related

How to correctly use Fetch in JavaScript and Django?

I am trying to make a METAR decoder as shown:
I am using fetch in Vanilla js and I plan to send the entered code to a Django view. From the Django view, the decoded data will be taken and displayed in the template.
views.py
def ToolsPageView(request):
if request.method == "POST":
jsonData = json.loads(request.body)
metarCode = jsonData.get('Metar')
return JsonResponse("Success", safe=False)
return render(request, 'app/tools.html')
urls.py
...
path("tools", views.ToolsPageView, name="tools")
tools.html
<div class="metar-code-decode">
<form method="POST" action="{% url 'tools' %}" id="metar-form">
{% csrf_token %}
<input type="text" placeholder="Enter METAR: " id="metar-value"> <br>
<input type="submit" id="metar-button">
</form>
</div>
tool.js
function getDecodedMetar() {
let formButton = document.querySelector("#metar-button");
formButton.onclick = function (e) {
let metarCode = document.querySelector("#metar-value").value;
sendMetar(metarCode);
//e.preventDefault();
//getMetar(metarCode);
};
}
function sendMetar(metarCode) {
fetch('/tools', {
method: "POST",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({
Metar: metarCode,
}),
});
}
I have used the same code for POST using fetch where I had to let user update his/her profile. And that worked. But, this does not work and the error keeps on changing from time to time after restarting the server. At the first try, there was no error produced and the server also showed a POST request being made. And the latest error which I am getting is "In order to allow non-dict objects to be serialized set the safe parameter to False." I get the same thing again and again even after setting safe=False within the JsonResponse(). Worth to note, request when converted to request.json() gives an error.
Am I using fetch wrongly? If yes, what is the correct way?
I'm not sure you have the flow right. The idea is that the button, when clicked, will call a function (fetch) that will send data to the view, which will decode it and send it back to the JavaScript, so that it could be displayed without reloading the entire page.
I think this might help:
let formButton = document.querySelector("#metar-button");
// When the button is clicked,
formButton.onclick = function(e) {
// do NOT send the form the usual way
e.preventDefault();
let metarCode = document.querySelector("#metar-value").value;
// Run the function that will send the code to the ToolsPageView
sendMetar(metarCode);
}
async function sendMetar(metarCode) {
const response = await fetch('/tools', {
method: "POST",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({
'Metar': metarCode,
}),
})
.then(response => response.json())
.then(data => {
console.log(data);
// extract the decoded value from the data sent back from the view
// display it by targeting the element in your html that you want
// to display it
});
}
And in your view,
def ToolsPageView(request):
if request.method == "POST":
jsonData = json.loads(request.body)
metarCode = jsonData.get('Metar')
# Remove the original JsonResponse
# return JsonResponse("Success", safe=False)
# and INSTEAD,
# Send the code back to the JavaScript
# I don't THINK you need safe=False here?
return JsonResponse({'MetarCode': metarCode})
return render(request, 'app/tools.html')

get value from a django form using javascript

I was trying for a long time to figure out how to get the value from a django.form using javascript, however I didn't get any straight answer to it.
here is my project:
views.py:
from django.shortcuts import render, redirect
from .forms import TextForm
from .Functions import GetData
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = TextForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
print("is valid")
text = form.cleaned_data['date']
x = GetData(text.day, text.month, text.year)
x.getInfo()
context = {
'text': text,
'form': form,
}
return render(request, 'index.html', context)
# if a GET (or any other method) we'll create a blank form
else:
form = TextForm()
print("not valid")
return render(request, 'index.html', {'form': form})
forms.py
from django import forms
class TextForm(forms.Form):
date = forms.DateField(widget=forms.SelectDateWidget(), label="inputDate")
let's say the html file is very basic, like this:
<form action=" " method="post" id="form">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
SO the main thing, that I need, is to get the date value from the form

Django: Could not parse the remainder

I'm trying to pass a response from JsonResponse as a parameter of specific function in views. But, got the following error instead
django.template.exceptions.TemplateSyntaxError: Could not parse the remainder: '${response.id_ajuan}' from '${response.id_ajuan}'
Here it is my code
url.py
url(r'^course-eksternal/review/(?P<id>\d+)/update$', course_eksternal.update_ajuan, name='update-ajuan')
views.py
# Function that pass the JsonResponse
def get_update_ajuan(request):
ajuan = Pengajuan.objects.get(pk=request.POST.get('ajuan_id'))
res = {
'id_ajuan': ajuan.id,
...
}
status_code = 200
return JsonResponse(res, status=status_code)
file.html
# Get the JsonResponse
success : function(response) {
$('.modal-body').empty().append(`
<div class="modal-body">
<form action="{% url 'app:update-ajuan' id=${response.id_ajuan} %}" method="POST"> # Error occurs here
...
`);
Your success function is javascript that is running in the front-end. Django is not running your front-end and there is no processing of django templates going on here, so you can't use any django template tags.
What you will need to do is figure out what the url is in your view get_update_ajuan and then pass the whole url back.
from django.urls import reverse
def get_update_ajuan(request):
ajuan = Pengajuan.objects.get(pk=request.POST.get('ajuan_id'))
res = {
'id_ajuan': ajuan.id,
'action_url': reverse("app:update-ajuan", kwargs={"id": ajuan.id},
...
}
status_code = 200
return JsonResponse(res, status=status_code)
and then use that value:
success : function(response) {
$('.modal-body').empty().append(`
<div class="modal-body">
<form action="${response.action_url}" method="POST"> # Error occurs here
...
`);

Ajax POST method to Django. Always results in "Not Ajax"

I have been trying to create an AJAX function which sends two JS variables, Score and Mistake, back to the Django backend and to update an extended user model with them.
To do this I started with an AJAX function which looks like this:
$(document).ready(function() {
$("#test").submit(function(event){
event.preventDefault();
console.log("form submitted!");
$.ajax({
type:"POST",
url:"/update/quiz/",
data: {
csrfmiddlewaretoken: window.CSRF_TOKEN,
'score': score,
'mistake' : mistake
},
success: function(){
$('#message').html("<h2>Contact Form Submitted!</h2>")
}
});
return false;
});
});
Views.py
class Quiz(TemplateView):
template_name='quiz.html'
def post(self, request, *args, **kwargs):
if request.is_ajax():
message = "Yes, Ajax!"
else:
message = "Not Ajax!"
return HttpResponse(message)
URLS.py
from django.urls import path
from home.views import HomepageName, Homepage, Quiz
from . import views
urlpatterns = [
path('quiz/', Quiz.as_view()),
path('update/quiz/', Quiz.post),
path('<slug:slug>/', HomepageName.as_view()),
path('', Homepage.as_view()),
]
And the template
<form method='POST' id ='test'>
{% csrf_token %}
<input type='submit' value='Test button'/>
<div id = 'message'>Initial text</div>
</form>
I've already tried to move around the URL routing and add a new URL thinking that would work but when the Submit button is clicked then it always loads a new page and then on that page it shows "Not Ajax!"
I assume that it is doing the default HTML form action and not the AJAX since their is no output to the console either which I added to get some more information
Thanks for all your help. Please comment if I need to provide more information!

How to integrate Django form with Ajax?

I've gone through many tutorials in how to integrate ajax with django form but all were complicated. I have a Signup model with Signup form and a views like the following.
models.py
from django.db import models
class SignUp(models.Model):
name = models.CharField(max_length=120, blank=True, null=True)
email = models.EmailField()
def __unicode__(self):
return self.email
and forms.py
from django import forms
from .models import SignUp
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUp
fields = ['name', 'email']
def clean_name(self):
name = self.cleaned_data.get('name')
return name
def clean_email(self):
email = self.cleaned_data.get('email')
try:
match = SignUp.objects.get(email=email)
except SignUp.DoesNotExist:
return email
raise forms.ValidationError('This email address is already subscribed.')
views.py
from django.shortcuts import render
from django.core.mail import send_mail
from django.conf import settings
from .forms import SignUpForm
def index(request):
form = SignUpForm(request.POST or None)
if form.is_valid():
name = form.clean_name()
email = form.clean_email()
instance = form.save()
subject = 'Bruke Church news'
from_email = settings.EMAIL_HOST_USER
to_email = [email]
contact_message = "%s:Thank you for signing up for our newsletter via %s. we'll be in touch" %(
name,
email)
send_mail (subject,
contact_message,
from_email,
to_email,
fail_silently=False)
context = {
"form": form
}
return render(request, "index.html",context)
and my html form looks like this
<form action="" method="POST">
{% csrf_token %}
{{form|crispy}}
<input type="submit" value="Sign up" class="btn btn-primary">
</form>
This code runs well but it loads the full page and I want to load only the form. After googling, I found a concept of Ajax but am really having problem in doing so. please help me Thank you
Example of Ajax Post
on button click submit
this method needs to run
put this in your HTML
function AddData(){
var name = $("#name").val();
var email = $("#email").val();
// You should extract each and every id from your form fields
var signupData = { name:name, csrfmiddlewaretoken: '{{ csrf_token }}',email:email};
$.ajax({
type: "POST",
url: "../../index/",
data: signupData,
success: function(data) {
alert("You Have Sucessfully Signed Up ");
},
statusCode: {
500: function() {
alert("You Have Already Signed Up ");
}
},
})
}
In your Views.py
def index(request):
if request.method == 'POST': # From Frontend we are getting the data in a POST method and we are checking if front end is giving POST Method or not
get_email = request.POST.get('email') # Taking The DATA from front end in form of POST to Django USER EMAIL ADDRESS
get_name = request.POST.get('name')# Taking The DATA from front end in form of POST to Django NAME
queryset_list = SignUp.objects.all().values_list("email",flat=True)# Performing a Django Query and getting all Signup Email Address
if get_email in queryset_list:
return HttpResponse(status=500)
else:
SignUp.objects.create(name=get_name,email=get_email)
return HttpResponse('')

Categories

Resources