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!
Related
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
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
I integrating a payment processor for my django app and now if payment was successful, I have a call back function written in JavaScript inside of the HTML and that gives me the transaction reference id. I want to send that reference id to my Django views for final verification.
I have tried almost all related solutions here on Stack Overflow none seems to solve my exact problem. The only thing I can do is to console.log() the reference id.
Here is my code
inside html
<script>
function payWithPaystack(){
var handler = PaystackPop.setup({
key: 'pk_test_somekey',
email: 'customer#email.com',
plan: "PLN_testcode",
metadata: {
custom_fields: [
{
display_name: "Mobile Number",
variable_name: "mobile_number",
value: "+2348012345678"
}
]
},
// if transaction was successful
callback: function(response){
var ref_ = response.reference
console.log(ref_)
},
onClose: function(){
alert('window closed');
}
});
handler.openIframe();
}
</script>
django views.py
def payment(request):
# here a variable will be capture the ref_
return render(request, template, context={})
You can write ajax call inside your callback function.
function PaymentCompleted(){
$.ajax({
type:"POST",
url :"/payment-completed/",
data:"reference_id=reference_id_here",
datatype:"json",
error:function(data){alert('Error:'+data);}
success:function(data){alert('OK!'+data.message+','+data.code);}
});
}
And at Django views:
from django.utils import simplejson
def paymnet_completed(request):
print "ajax request called"
print request.GET['reference_id']
return_dict = {'message': 'Payment Successful','code':200}
json = simplejson.dumps(return_dict)
return HttpResponse(json, mimetype="application/x-javascript")
I Hope this might have helped.
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('')
I have commenting system that works(at least works in the backend). The problem is every time user submits comment the page gets refreshed. I wrote an ajax function for this, but since I'm a beginner I was expecting to get an error and I did. I got 500 internal error.I'm not sure what I did wrong though. Here;s my code
<div class='reply_comment'>
<form method="POST" action='{% url "comment_create" %}'>{% csrf_token %}
<input type='hidden' name='post_id' id='post_id' value='{% url "comment_create" %}'/>
<input type='hidden' name='origin_path' id='origin_path' value='{{ comment.get_origin }}'/>
<input type='hidden' name='parent_id' id='parent_id' value='{{ comment.id }}' />
{% crispy comment_form comment_form.helper %}
</form>
</div>
<script>
$(document).on('submit','.commentForAjax', function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'/comment/create',
data:{
post_id:$('#post_id').val(),
origin_path:$('origin_path').val(),
parent_id:$('#parent_id').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success:function(){
alert('it worked');
}
})
})
</script>
I have url like this
url(r'^comment/create/$', 'comment_create_view', name='comment_create'),
Edit:
I didn't post my views.py because it's huge, and thought I wrote ajax wrong. I'll post my view
def comment_create_view(request):
if request.method == "POST" and request.user.is_authenticated():
parent_id = request.POST.get('parent_id')
post_id = request.POST.get("post_id")
origin_path = request.POST.get("origin_path")
try:
post = Post.objects.get(id=post_id)
except:
post = None
parent_comment = None
if parent_id is not None:
try:
parent_comment = Comment.objects.get(id=parent_id)
except:
parent_comment = None
if parent_comment is not None and parent_comment.post is not None:
post = parent_comment.post
form = CommentForm(request.POST)
if form.is_valid():
comment_text = form.cleaned_data['comment']
if parent_comment is not None:
# parent comments exists
new_comment = Comment.objects.create_comment(
user=MyProfile.objects.get(user=request.user),
path=parent_comment.get_origin,
text=comment_text,
post = post,
parent=parent_comment
)
#affected_users = parent_comment.get_affected_users()
#print "this is"
affected_users = parent_comment.get_affected_users()
return HttpResponseRedirect(post.get_absolute_url())
else:
new_comment = Comment.objects.create_comment(
user=MyProfile.objects.get(user=request.user),
path=origin_path,
text=comment_text,
post = post
)
return HttpResponseRedirect(post.get_absolute_url())
else:
messages.error(request, "There was an error with your comment.")
return HttpResponseRedirect(origin_path)
else:
raise Http404
I forgot to add this here
urlpatterns += patterns('comments.views',
Edit two,
the reason I'm using class for commentForAjax rather than id is because I want to have same effect for my reply-comment code too. I want one ajax function for both of my forms.
<div class="make_reply">
<a href='#' class='reply_btn'>reply</a>
<div class='reply_comment'>
<form method="POST" action='{% url "comment_create" %}'>{% csrf_token %}
<input type='hidden' name='post_id' id='post_id' value='{% url "comment_create" %}'/>
<input type='hidden' name='origin_path' id='origin_path' value='{{ comment.get_origin }}'/>
<input type='hidden' name='parent_id' id='parent_id' value='{{ comment.id }}' />
{% crispy comment_form comment_form.helper %}
</form>
</div>
</div>
Edit:
here's my django error, I didn't know how to do it but followed daniel's guidance. is this the one?
RuntimeError at /comment/create
You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/comment/create/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
Request Method: POST
Request URL: http://127.0.0.1:8000/comment/create
Django Version: 1.8.4
Python Executable: env/bin/python
Python Version: 2.7.6
Python Path: [ 'env/lib/python2.7', 'env/lib/python2.7/plat-x86_64-linux-gnu', 'env/lib/python2.7/lib-tk', 'env/lib/python2.7/lib-old', 'env/lib/python2.7/lib-dynload', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', 'env/local/lib/python2.7/site-packages', 'env/lib/python2.7/site-packages']
Server time: 화요ì¼, 15 3ì›” 2016 18:48:14 +0900
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main',
'comments',
'notifications',
'news',
'tastypie',
'userena',
'guardian',
'easy_thumbnails',
'accounts',
'crispy_forms',
'django_select2',
'actstream',
'annoying',
'embed_video',
'ckeditor',
'ckeditor_uploader',
'whoosh',
'haystack')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
108. response = middleware_method(request)
File "env/local/lib/python2.7/site-packages/django/middleware/common.py" in process_request
84. "settings.") % (new_url[0], new_url[1]))
Exception Type: RuntimeError at /comment/create
Exception Value: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/comment/create/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
Request information:
GET: No GET data
POST:
post_id = u'/comment/create/'
csrfmiddlewaretoken = u'gw8ohxs2ZPVonPf812iM3vCAK2NnxAde'
parent_id = u'216'
FILES: No FILES data
The exception you posted is quite informative:
Exception Value: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/comment/create/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
Request information:
So you have to add a trailing slash to your url in the ajax method:
<script>
$(document).on('submit','.commentForAjax', function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'/comment/create/', //ADD THE SLASH!
data:{
post_id:$('#post_id').val(),
origin_path:$('origin_path').val(),
parent_id:$('#parent_id').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success:function(){
alert('it worked');
}
})
})
</script>
There is something wrong in your script.
<script>
...
origin_path:$('origin_path').val(),
...
</script>
origin_path is an id not a tag. Replace by this
<script>
...
origin_path:$('#origin_path').val(),
...
</script>
For more help you should print the server error message