Using AJAX to create an Object which then appears in dropdown box - ajax

Hi I've run into a problem where I am trying to make it so when a button is clicked an object can be made. I can't get it to work as for some reason it will not validate, however if I change input type to submit it works fine.
But the problem is when I use it as submit the page redirects which defeats the purpose of using AJAX.
I can't seem to find a good tutorial for what I'd like to do, any help or links would really be appreciated!
Models
class MemberRole(models.Model,get_fields):
name = models.CharField(max_length = 20)
Form
class MemberRoleForm(forms.ModelForm):
class Meta:
model = MemberRole
Views
This view builds the form for the memberrole model
def add_member(request):
model_url = 'member-add'
rform = MemberRoleForm(instance=MemberRole())
return render_to_response('create_model.html', {'role_form': rform,'model_url': model_url,},context_instance=RequestContext(request))
This ajax called view
#require_POST
def ajax(request):
data = request.POST.get("rolename","")
if request.method == 'POST':
rform = MemberRoleForm(request.POST, instance=MemberRole())
if rform.is_valid():
new_role = rform.save()
new_role.name = data
return HttpResponse("SuccessFully Saved")
else:
return HttpResponse("Error in saving")
Template
<div id="addRoleOnMemberForm">
<form id = "addrole" onsubmit= "return false;" method="POST">
{% csrf_token %}
{% for field in role_form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }} //#id_name is in here
{% endfor %}
<input id="addrolebutton" type="button" onclick = "createit()" value="Add New Role"/>
</div>
{% for x in role_list %}
<div>
<p> This shows a role was made </p>
</div>
{% endfor %}
Script
<script>
function createit(){
$.ajax({
type: "POST",
url:"ajax",
dataType:"json",
async: true,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
rolename: $('#id_name').val()
},
});
}
</script>

I've finally managed to get it to work. :)
I have an add_member view which allows the creation of a memberrole object if it is not available in the member.role dropdown field. The memberrole object on creation will be added without a page reload to the dropdown field so it can be selected immediatly.
I'm not entirely sure if this would be the correct way of coding it, I've included all the source and hopefully it helps someone like me. Comments would be appreciated!
Models
class MemberRole(models.Model,get_fields):
name = models.CharField(max_length = 20)
class Member(models.Model,get_fields):
first_name = models.CharField(max_length = 20)
last_name = models.CharField(max_length = 20)
role = models.ForeignKey(MemberRole, null = True, blank = True)
Forms
class MemberForm(forms.ModelForm):
class Meta:
model = Member
Script
<script>
function createit(){
$.ajax({
type: "POST",
url:"addrole",
dataType:"json",
async: true,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
rolename: $('#role_name').val()
},
success: function (json,rolename){
$('#output').html(json.message); // Prints a message to say that the MemberRole object was created
$('#roleExistsMemberForm').load(document.URL + ' #roleExistsMemberForm'); //Refreshes the dropdown box so that the newly created MemberRole can be selected
}
});
}
</script>
Views
def add_role(request):
model_url = 'role-add'
new_role = request.POST.get("rolename","")
role_list = MemberRole.objects.all()
response_data= {}
if new_role:
x = MemberRole()
x.name = new_role
x.save()
response_data['message'] = new_role + " was created"
else:
response_data['message'] = 'Nothing created'
return HttpResponse(json.dumps(response_data),content_type="application/json")
def add_member(request):
model_url = 'member-add'
if request.method == "POST":
mform = MemberForm(request.POST, instance=Member())
if mform.is_valid():
new_member = mform.save(commit=False)
new_member.save()
return HttpResponseRedirect('members')
else:
mform = MemberForm(instance=Member())
return render_to_response('create_model.html', {'member_form': mform, 'model_url': model_url,},context_instance=RequestContext(request))
create_model.html
{% for field in member_form %}
{% if field.label == 'Role' %}
<div id="roleExistsMemberForm">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% else %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endif %}
{% endfor %}
<div id="addRoleOnMemberForm">
<form onsubmit="return false;">
{% csrf_token %}
<input id= "role_name" type="text"/>
<input id="addrolebut" type="button" onclick = "createit()" value="Add New Role"/>
</div>
<div id="output">
<p>Nothing here</p>
</div>

Related

How to use values passed by jquery/ajax in django view

How do I retrieve and use the data passed to view via ajax? In this example I'm trying to implement a reddit like upvote/downvote system
html/js:
{% for post in posts %}
<h2>{{ post.title }}</h2>
{{ post.upvotes }}<button data-id="{{post.id}}" data-vote="up" class="vote" type="submit">Upvote</button>
{{ post.downvotes }}<button data-id="{{post.id}}" data-vote="down" class="vote" id="downvote" type="submit">Downvote</button>
{% endfor %}
<script>
$(".vote").click(function () {
var id = $(this).data("id"); //get data-id
var vote_type = $(this).data("vote"); //get data-vote
};
$.ajax({
url: '/ajax/upvote/',
data: {
'id': id,
'vote_type':vote_type,
}
});
</script>
urls.py:
url(r'^ajax/upvote/$', views.upvote, name='upvote'),
view:
def upvote(request):
#how do i use 'id' and 'vote_type' values here?
You need to first edit your javascript to send the csrf token, and register a POST url in your url.py .
{% for post in posts %}
<h2>{{ post.title }}</h2>
{{ post.upvotes }}<button data-id="{{post.id}}" data-vote="up" class="vote" type="submit">Upvote</button>
{{ post.downvotes }}<button data-id="{{post.id}}" data-vote="down" class="vote" id="downvote" type="submit">Downvote</button>
{% endfor %}
<script>
$(".vote").click(function () {
var id = $(this).data("id"); //get data-id
var vote_type = $(this).data("vote"); //get data-vote
};
$.ajax({
url: '/ajax/upvote/',
data: {
'id': id,
'vote_type':vote_type,
csrfmiddlewaretoken: '{{ csrf_token }}'
}
});
</script>
Now you can access the data you sent in your views.py in a usual way:
def upvote(request):
sentence= request.POST.get("id","")
upvote = request.POST.get("upvote","")
#continue doing your stuffs here...
Hope this helps.

Like Button In Django Ajax

my like button is working fine without ajax with page reloading but it is having problem when done by implementing ajax. the like and unlike is happening in the backend (like is created and deleted in database on ajax Post request), but the like count,like,unlike button does not change in response on ajax post request, until the page is reloaded. Need Help
here is the post model and like model for posting image and liking it in models.py
class PostModel(models.Model):
user = models.ForeignKey(UserModel)
image = models.FileField(upload_to='user_images')
image_url = models.CharField(max_length=255)
caption = models.CharField(max_length=240)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
has_liked = False
#property
def like_count(self):
return len(LikeModel.objects.filter(post=self))
class LikeModel(models.Model):
user = models.ForeignKey(UserModel)
post = models.ForeignKey(PostModel)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
url for liking in urls.py
url(r'^like/', like_view),
views.py
def like_view(request):
user = check_validation(request)
if user and request.method == 'POST':
form = LikeForm(request.POST)
if form.is_valid():
#post_id = form.cleaned_data.get('post').id
post_id=request.POST['post']
existing_like = LikeModel.objects.filter(post_id=post_id, user=user).first()
if not existing_like:
LikeModel.objects.create(post_id=post_id, user=user)
else:
existing_like.delete()
return redirect('/feed/')
else:
return redirect('/login/')
template.html
{% for post in posts %}
<form id="like_form">
{% csrf_token %}
<input type="hidden" name="post" id="post_id"value="{{ post.id }}">
{% if post.has_liked %}
<button class="btn btn-link unlike"type="submit"><i class="fa fa-heart" aria-hidden="true"style="color:#ed4956;"></i></button>
{% else %}
<button class="btn btn-link like"type="submit"><i class="fa fa-heart-o" aria-hidden="true"style=color:#333333;"></i></button>
{% endif %}
</form>
{% endfor %}
Javascript code
<script>
$(document).on('submit','#like_form',function (e) {
e.preventDefault();
$.ajax({
type:'POST',
url:'/like/',
data:{
post:$('#post_id').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success:function (response) {
console.log("liked");
}
});
});
</script>

Django-registration ajax post form

registration and to make validations I will be submitting the form via Ajax.
I have checked other posts and tried some options, but the csrf_token gives a jscript error
Uncaught SyntaxError: Unexpected identifier
The form is for login, and if data is entered ok, the form submits ok even with the error. But if the entered data is wrong, just does nothing.
$(document).on("submit", this.id, function(e) {
e.preventDefault();
var frm = e.target.id;
var frmData = $("#"+frm).serialize();
$.ajax({
type: "POST",
url: '{% url 'django.contrib.auth.views.login' %}',
contentType: 'application/x-www-form-urlencoded;charset=utf-8',
csrfmiddlewaretoken : '{% csrf_token %}',
data: frmData,
success: function(data)
{
console.log('success');
},
error: function (data) {
console.log('error');}
});
I also have the csrf_token tag in the form.
I think this will solve your problem:
// ajax components
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;
};
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
And what my form looked like:
<ul class="sub-menu collapse" id="settings">
<form id="glucose_boundary_form" action="/glucose/goals" method="POST">
{% csrf_token %}
{{ glucose_boundary_form.as_p }}
</form>
<button type="submit" id="glucose_goals">Submit</button>
</ul>
What a button click looked like
$('button#glucose_submit').click(function() {
$.ajax({
url:'glucose/submit',
type: 'POST',
data: $('form#glucose_form').serialize(),
success: function(data) {
document.getElementById("glucose_form").reset();
}
});
});
EDIT:
Here is my login and registration view. Although I do not use ajax for registration. The form validation happens automatically for the login page. Hope they helps you see what I'm doing and how you might apply my answer.
from django import forms
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render
from django.contrib.auth.models import User
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
from loginregistration.models import loginForm, registrationForm
# Login user method
def login(request):
if request.user.is_authenticated():
return HttpResponseRedirect('')
form = loginForm(request.POST or None)
if request.POST and form.is_valid():
user = form.login(request)
if user:
auth_login(request, user)
return HttpResponseRedirect('/') # Redirect to a success page.
return render(request, 'login.html', {'form': form})
# Logout user method
def logout(request):
auth_logout(request)
return HttpResponseRedirect(reverse('loginregistration.views.login')) # Redirect to a success page.
# Register user method
def register(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/')
if request.method == 'POST': # If the form has been submitted...
form = registrationForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
password = form.cleaned_data['password']
username = form.cleaned_data['username']
email = form.cleaned_data['email']
# Tries to create a new user and add them to the database
try:
User.objects.create_user(username, email=email, password=password, first_name=first_name, last_name=last_name)
except:
#Add error
return HttpResponseRedirect('#ERROR')
return HttpResponseRedirect('/login') # Redirect after POST
else:
form = registrationForm() # An unbound form
return render(request, 'register.html', {'form': form})
Here is my login template:
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<form method="post" action="" id="login" class="container"
style="background-color: #FFFFFF; max-width: 450px; border-radius: 8px;">
{% csrf_token %}
<h1 style="text-align: center">Login to Your Account</h1>
<div class="form-group container" style="max-width: 300px;">
{{form.as_p}}
<button type="submit" class="btn btn-primary">Login</button>
Create an account
</div><br>
</form>
<script type="text/javascript">document.forms.login.id_username.focus();</script>
{% endblock %}
Here is my registration template:
{% extends "base.html" %}
{% block title %}Create Account{% endblock %}
{% block content %}
<form method="post" action="" id="register" class="container "
style="background-color: #FFFFFF; max-width: 450px; border-radius: 8px;">
{% csrf_token %}
<h1 style="text-align: center">Register for an Account</h1>
<b></b>
<p style="text-align: center">WARNING: This is a prototype website for testing purposes only. For security reasons, do not use your real credentials!</p>
<div class="form-group container" style="max-width: 300px;">
{{form.as_p}}
<button type="submit" class="btn btn-primary btn-block">Create The Account</button>
</div>
</form>
<script type="text/javascript">document.forms.register.id_firstName.focus();</script>
{% endblock %}

how to clear the form fields after submit data through ajax in symfony2?

my new.html.twig code is given below. How do I clear the form fields after the form submission?
{% extends '::base.html.twig' %}
{% block body -%}
<h1>Proposals creation</h1>
<form action="{{ path('proposals_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<p>
<button type="submit">Create</button>
</p>
</form>
<ul class="record_actions">
<li>
<a href="{{ path('proposals') }}">
Back to the list
</a>
</li>
</ul>
<div id="result"></div>
{% endblock %}
{% block javascripts %}
<script src="{{ asset('js/jquery-1.10.2.js') }}" type="text/javascript"></script>
<script type="text/javascript">
$().ready(function() {
$("form").submit(function(e) {
e.preventDefault();
var $url = $(this).attr('action');
var $data = $(this).serialize();
$.ajax({
type: "POST",
url: $url,
data: $data
}).done(function( result ) {
if(result.success) {
$('#result').html('<span>Monetary expense correctly saved!<br/> The data are:<br/>id: '+ result.id +'<br/>descrition: '+ result.description +'<br/>proposalname: '+ result.proposalname +'<br/>status: '+ result.status +'</span>');
}
});
});
});
</script>
{% endblock %}
Use HTMLFormElement.reset() to revert all <form> fields to their defaults.
$("form").submit(function(e) {
e.preventDefault();
var $url = $(this).attr('action');
var $data = $(this).serialize();
$.ajax({
type: "POST",
url: $url,
data: $data
}).done(function( result ) {
if(result.success) {
$('#result').html('<span> ... </span>');
}
});
this.reset(); // formElement.reset()
});
reset() resets the form to its initial state. This method does the same thing as clicking the form's reset button. If a form control (such as a reset button) has a name or id of reset it will mask the form's reset method.

Django - after submitting invalid form submit button upon click redirects

I have a django project in which i have a form in a div being loaded by ajax.
when I submit the form with empty fields it returns the form with the required fields shown.
when I hit submit again it redirects to the action of the form instead of reloading the form in the div and showing errors as it does the first time I submit.
does anyone have any idea where the error might be occurring? I imagine somewhere in the ajax or view in my django project.
here is what is returned by the second submit:
{"success": false, "form": "<head>\n\n</head>\n<body>\n<form action=\"/cookbook/createrecipe/\" method=\"POST\" name=\"recipeform\" id=\"createrecipeform\">\n\t<table>\n\t\t<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='c5ea952ee2144b377b375d91b0843c75' /></div>\n\t\t<tr><th><label for=\"id_name\">Name:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_name\" type=\"text\" name=\"name\" maxlength=\"200\" /></td></tr>\n<tr><th><label for=\"id_author\">Author:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_author\" type=\"text\" name=\"author\" maxlength=\"100\" /></td></tr>\n<tr><th><label for=\"id_picture\">Picture:</label></th><td><input type=\"file\" name=\"picture\" id=\"id_picture\" /></td></tr>\n<tr><th><label for=\"id_ingredients\">Ingredients:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_ingredients\" rows=\"10\" cols=\"40\" name=\"ingredients\"></textarea></td></tr>\n<tr><th><label for=\"id_steps\">Steps:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_steps\" rows=\"10\" cols=\"40\" name=\"steps\"></textarea></td></tr>\n<tr><th><label for=\"id_prep_time\">Prep time:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input type=\"text\" name=\"prep_time\" id=\"id_prep_time\" /></td></tr>\n<tr><th><label for=\"id_type\">Type:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><select name=\"type\" id=\"id_type\">\n<option value=\"\" selected=\"selected\">---------</option>\n<option value=\"SW\">Sandwich</option>\n<option value=\"AP\">Appetizers</option>\n<option value=\"SD\">Sauces and Dressings</option>\n<option value=\"SS\">Soups and Salads</option>\n<option value=\"VG\">Vegetables</option>\n<option value=\"RG\">Rice, Grains and Beans</option>\n<option value=\"PA\">Pasta</option>\n<option value=\"BR\">Breakfast</option>\n<option value=\"MT\">Meat</option>\n<option value=\"SF\">Seafood</option>\n<option value=\"BP\">Bread and Pizza</option>\n<option value=\"DT\">Desserts</option>\n</select><input type=\"hidden\" name=\"reset_recipe\" id=\"id_reset_recipe\" /></td></tr>\n\t</table>\n\t<p><input type=\"submit\" value=\"Submit\"></p>\n</form>\n</body>"}
here is my ajax code:
<script type="text/javascript">
$(document).ready(function(){
var form = $('form#createrecipeform');
form.submit(function(e) {
e.preventDefault();
console.log('ajax form submission function called successfully.');
//form = $(this);
console.log(form)
var serialized_form = form.serialize();
$.ajax({ type: "POST", 
url: $(this).attr('action'),
data: serialized_form, 
success: (function(data) { 
console.log('ajax success function called successfully.');
data = $.parseJSON(data);
if (data.success) {
console.log('success');
} else {
console.log('failure');
var newForm = data.form;
form.replaceWith(newForm);
}
})
});
return false;
});
});
</script>
here is the view: (createrecipe is the action of the form and account is the page that is loading the ajax)
def createrecipe(request):
print "entering createrecipeview"
if request.method == 'POST':
print "form is a post"
form = RecipeForm(request.POST)
print form.errors
if form.is_valid():
print "form is valid"
form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
form = form.save()
t = loader.get_template('cookbook/create_form.html')
c = RequestContext(request, {
'form': form,
})
data = {
'replace': True,
'form': t.render(c),
'success': True,
}
json = simplejson.dumps(data)
return HttpResponse(json, mimetype='text/plain')
else:
print "form is invalid"
form = RecipeForm(request.POST)
t = loader.get_template('cookbook/create_form.html')
c = RequestContext(request, {
'form':form,
})
data ={
'form': t.render(c),
'success': False,
}
json = simplejson.dumps(data)
return HttpResponse(json, mimetype='text/plain')
def account(request):
user = request.user
if request.user.is_authenticated():
cookbooks = user.cookbooks
if cookbooks.all().exists():
cookbook = cookbooks.all()[0]
form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
recipe_list = cookbook.recipes.all()
else:
raise Http404
else:
return HttpResponseRedirect('/accounts/login')
t = loader.get_template('cookbook/account.html')
c = RequestContext(request, {
'form': form,
'recipe_list': recipe_list
})
return HttpResponse(t.render(c))
here is the create_form.html template:
<head>
</head>
<body>
<form action="{% url cookbook.views.createrecipe %}" method="POST" name="recipeform" id="createrecipeform">
<table>
{% csrf_token %}
{{ form.as_table }}
</table>
<p><input type="submit" value="Submit"></p>
</form>
</body>
and here is the account template that includes the create_form template:
{% extends "cookbook/base.html" %}
{% load pagination_tags %}
{% load comments %}
<h1>{{ user }}'s Cookbook</h1>
<ul>
{% block nav-cookbooks %}
<li><a class="nav-inactive" href="/cookbooks/">Cookbooks</a></li>
{% endblock %}
{% block nav-account %}
<li><a class="nav-active" href="/account/">My Cookbook</a></li>
{% endblock %}
</ul>
{% block content %}
{% autopaginate recipe_list 6 %}
<div id="recipe_cont">
{% for recipe in recipe_list %}
<div class="recipe">
<div class="button">
<img src="{{ STATIC_URL }}chicknbraw.jpg" alt="" height="70" width="70" style="display:inline;" />
<h4>{{ recipe.name }}</h4>
</div>
<h5>{{ recipe.author }}</h5>
<h5>Prep Time: {{ recipe.prep_time }} minutes</h5>
<h6>Add Recipe
Remove Recipe</h6>
</div>
{% endfor %}
</div>
<div id="popupContact" class="popup">
<a id="popupContactClose" style="cursor:pointer;float:right;">x</a>
<p id="contactArea">
<h1 style="text-align:center">Create New Recipe</h1>
{% include 'cookbook/create_form.html' %}
</p>
</div>
<div id="backgroundPopup">
</div>
<div id="col2-footer">
{% paginate %}
<p id="recipe_order_text"> order by: abc|date
</div>
{% endblock %}
{% block footer %}
<a class="create" style="cursor:pointer" >Create New Recipe</a>
{% endblock %}
sorry for putting so much code but it all seems to rely upon another piece of code so I figured all relevant code would be helpful
thanks for any help you can give me
katie
In your javascript, you're hijacking the form so that it submits via ajax, but then you're calling replaceWith on the form, so your hijacked form gets obliterated and is replaced with a new, non-hijacked form. To solve this you can either
1) Only replace the content of the form - this should work since you're only attaching events to the form itself and not its child elements
2) Write your js as a function which you can call firstly on the initial form, and subsequently on any new forms loaded via ajax.
UPDATE: for example,
<script type="text/javascript">
$(document).ready(function(){
function hijack() {
var form = $('form#createrecipeform');
form.submit(function(e) {
e.preventDefault();
console.log('ajax form submission function called successfully.');
//form = $(this);
console.log(form)
var serialized_form = form.serialize();
$.ajax({ type: "POST",
url: $(this).attr('action'),
data: serialized_form,
success: (function(data) {
console.log('ajax success function called successfully.');
data = $.parseJSON(data);
if (data.success) {
console.log('success');
} else {
console.log('failure');
var newForm = data.form;
form.replaceWith(newForm);
hijack();
}
})
});
return false;
});
};
hijack();
});
</script>

Resources