I have a form in django. it's 'composing mail' form. I send this form from view to my template and i apply ckeditor to chang the body style. i want this form to be posted by ajax. and when ckeditor is used, value of body field isn't send with request.POST. i use this line of code to use ckeditor:
CKEDITOR.replace('id_body');
(without using ckeditor, every thing works fine.)
<form id="compose_form" action="compose/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div>
<div class="form-field">
<label for="id_recipient">{% trans 'recipient' %}:</label>
{{ form.recipient }}
{{ form.recipient.errors }}
</div>
<div class="form-field">
<label for="id_subject">{% trans 'subject' %}:</label>
{{ form.subject }}
{{ form.subject.errors }}
</div>
</div>
<div class="form-field">
{{ form.body }}
{{ form.body.errors }}
</div>
<input id="messages-submit" type="submit" value=""Send"/>
</div>
</form>
and i use this script to send form data via ajax:
<script type="text/javascript">
$(function() {
$('#compose_form').submit(function() {
var temp = $("#compose_form").serialize();
$.ajax({
type: "POST",
data: temp,
url: 'compose/',
success: function(data) {
// do s.th
}
});
return false;
});
});
</script>
with this script, body value isn't send to request.POST(i mean it sends empty string in body field), when i add the below line to my script, it sends value of body field, but it isn't ajax any more. Can you please help me what to do?
The reason that the data in the editor isn't included in the form is because the editor isn't a part of the form. It needs to update the form element you have associated it with. For this to happen you need to tell the editor to update the form element.
So in the submit function for your form you need to grab data from the editor.
This should do the trick:
$(function() {
$('#compose_form').submit(function() {
for (var instance in CKEDITOR.instances)
CKEDITOR.instances[instance].updateElement();
var temp = $("#compose_form").serialize();
etc etc...
I also had the same issue with django-ckeditor,What I tried is
<script type="text/javascript">
for (var instance in CKEDITOR.instances)
CKEDITOR.instances[instance].updateElement();
then checked the instance name by:
console.log(instance)
it gave "id_Your_Message" ,,So I did:
var temp = $("#id_Your_Message").val()
it works fine
<script type="text/javascript">
$(function () {
$('#submit_button_id').click(function () {
$.post("action post file url", $("#form_id").serialize(), function (data) {});
});
});
</script>
I hope above script may be help you
Related
i am working on blog project, when i click submit post would be created and ajax will live reload the page. its working as i expected but as soon as my post reaches 20 it would stop appending to that perticular div, but the model object is being created correctly,when i go to admin there would 25,35 or 50 model object but only first 20 would be appended?
ajax
$(document).ready(function(){
// $("button").click(function() {
// $("html, body").animate({
// scrollTop: $('html, body').get(0).scrollHeight
// }, 2000);
// });
$(document).on('submit','#post_form',function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url:"{% url 'create' %}",
data:{
message: $('#message').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
},
success:function(){
}
});
});
setInterval(function(){
$.ajax({
type:'GET',
url:"{% url 'comments' %}",
success:function(response){
$('.display').empty();
for(var key in response.comments){
if (response.comments[key].name != '{{request.user}}'){
var temp = "<div class='message_area'><p id = 'author'>"+response.comments[key].name+"</p><p id='messagetext'>"+response.comments[key].message+"</p></div><br>"
$(".display").append(temp);
}
if (response.comments[key].name == '{{request.user}}'){
var user_temp = "<div class='message_area_owner'><p id='messagetext_owner'>"+response.comments[key].message+"</p></div><br><br><br>"
$(".display").append(user_temp);
}
}
},
error:function(response){
console.log("no data found")
}
});
}, 500);
});
html
{% if request.user.is_authenticated %}
<div class="display"></div>
<div class="input">
<form id="post_form">
{% csrf_token %}
<input type="text" id="message" name = 'message' autocomplete="off" onfocus="this.value=''">
<button type="submit" id="submit" onclick="scroll()">SENT</button>
</form>
</div>
{%else%}
<a class="btn btn-danger" href="{% url 'login' %}" style="text-align: center;">login</a>
<a class="btn btn-danger" href="{% url 'register' %}" style="text-align: center;">register</a>
{% endif%}
views and models as normal
when i press post btn model object is getting created but not appending to .display div if it has already 20 divs in that
actually my question is why you want to get all comments via ajax? the object has some comments available when user requested the page, so you could render that available ones to the template. and just use ajax to get the new one that user may add. the last one and also it's easier to get this last one in the success method of ajax itself when comment has been sent and if it was successfully added to database. also you may need append function in javascript to append the response to the dom. and use render_to_response in the django part so to render a pace of template which contains the comment box(some magic use component like a frontend framework) and then append that pace of rendred html to the dom.
There are a lot of different posts about all parts of this, I just can't quite figure out how it all fits together.
I have name that is displayed with an update button next to it. When the update button is clicked it shows a form to update the name. In the form is a save changes button. When the changes are saved, it should reload the name at the top, and should the update button be clicked again, the form should show the new name info.
urls.py
path('profile/<int:pk>/', views.customer_profile, name='profile'),
path('update-profile/<int:pk>/', views.update_profile, name='update-profile'),
views.py
def customer_profile(request, pk):
name = get_object_or_404(CEName, id=pk)
name_form = NameForm(instance=name)
return render(
request,
'customer/customer_profile.html',
{'name':name, 'NameForm': name_form}
)
def update_profile(request, pk):
if request.POST:
name_form = NameForm(request.POST)
if name_form.is_valid():
name_form.save()
name = get_object_or_404(CEName, id=pk)
context = {'name':name, 'NameForm': name_form}
html = render_to_string('customer/customer_profile.html', context)
return HttpResponse(html, content_type="application/json")
template.html
<div id="name" class="container d-flex justify-content-between pt-1">
{{ name }}
<button id="update_button" class="bold btn btn-main btn-sm button-main">UPDATE</button>
</div>
<div id="div_NameForm" class="container" style="display: none;">
<hr size="3px">
<form id="NameForm" method="POST" data-url-name="{% url 'customer:update-profile' name.id %}">
{% csrf_token %}
{{ NameForm.as_p }}
<br>
<button type="submit" id="save_changes" class="btn btn-main button-main btn-block">Save Changes</button>
</form>
</div>
<script src="{% static 'ce_profiles/ce_profiles_jquery.js' %}"></script>
jquery.js
$('#save_changes').click(function() {
var NameForm = $('#NameForm');
$.ajax({
type: 'post',
url: NameForm.attr('data-url-name'),
data: NameForm.serialize(),
dataType: 'json',
success: function(data, textStatus, jqXHR) {
$('#name').html(data);
}
});
});
The code for the update button toggle is not displayed.
In your jQuery, to start with.
- First, you could (some may say should) have put a submit event handler on the on the form instead of a click event for button.
- Second, you are doing an AJAX call so you should prevent form submission using .preventDefault() on the submit event that was trigged when the button was pressed. This will prevent the page from reloading.
- Third, in your ajax success callback you should use text() instead of html() since name I imagine is text and not html, however that's just an assumption.
$('#NameForm').on('submit', function(evt) {
evt.preventDefault();
var NameForm = $('#NameForm');
$.ajax({
...
success: function(response) {
$(#name).text(response); // or response.name or whatever
}
});
})
I am creating an app with Flask and JQuery which accepts input from user like this
<form>
{% for i in range(length) %}
<div class="form-group has-success has-feedback">
<label for="question">Question {{ i+1 }}: {{ qlist[i] }}</label>
<textarea class="form-control" rows="5" id="CAT_Custom_{{ i+1 }}" name="CAT_Custom_{{ i }}"></textarea>
<span class="glyphicon glyphicon-ok form-control-feedback"></span>
</div>
{% endfor %}
<input type="submit" name="submit" class="submit action-button" value="Submit" />
</form>
here qlist is a list of questions like this
['What is a Network?', 'What is a Router', ...]
Before submitting the form I want to make sure that each question has an answer of at-least 100 words typed by user. So I'm trying to use a function called process which returns error or success based on the length of answer.
#app.route("/process", methods=["POST"])
def process():
name = request.form['name']
if len(name.split()) >= 100:
return jsonify({'success' : name})
return jsonify({'error': 'No data'})
Now the problem is since my form inputs are dynamically created how do I check if every individual answer is of length 100 words or above.
My attempt was like this but it changes every textarea inputs not just the one with less number of words.
$(function() {
$('form').on('submit', function() {
$.ajax({
data : {
name : $(this).find('.form-control').val()
},
type : 'POST',
url : '/process'
})
.done(function(data) {
if(data.error) {
$('.form-group').find('span').removeClass('glyphicon-ok').addClass('glyphicon-remove');
} else {
$('.form-group').find('span').removeClass('glyphicon-remove').addClass('glyphicon-ok');
}
});
event.preventDefault();
});
});
I found a solution to my problem like this
$(function() {
$('.form-group').focusout( function(event) {
var target = $(this);
$('.form-group').each(function() {
var target = $(this);
$.ajax({
data : {
name : target.find('.form-control').val()
},
type : 'POST',
url : '/process'
}) // Ajax close
.done(function(data) {
if(data.error) {
target.find('span').removeClass('glyphicon-ok').addClass('glyphicon-remove');
} else {
target.find('span').removeClass('glyphicon-remove').addClass('glyphicon-ok');
} // if close
}); // done close
event.preventDefault();
}); // each close
});
});
How do I get the HTML component that contains the button which has been clicked with jQuery? After a button is clicked I need to get the invite object that corresponds to the clicked button and send a post request to a given link.
{% if invites %}
{% for invite in invites %}
<p>Your invites:</p>
<div class="row">
<label style="display: block">Invite from {{ invite.initiator }} to join his conference!</label>
<button type="button" id="ButtonId">Accept invite</button>
</div>
{% endfor %}
{% endif %}
The script:
<script type="text/javascript">
$(function() {
$('#ButtonId').on('click',function(){
!$(this).hasClass('ButtonClicked') ? addClass('ButtonClicked') : '';
$('#ButtonId').val('Done');
var data = {
};
$.ajax({
url: '/api/send_invite/' + /*the username*/,
data: JSON.stringify(data , null, '\t'),
contentType: 'application/json;charset=UTF-8',
type: 'POST',
success: function() {
}
});
});
});
</script>
Your "HTML component" is what the button is wrapped in ? If so, In order to get the element that contains the button that is being clicked (the "parent" of the button) you can do something like this:
$('#myButton').on('click',function(){
var buttonParent = $(this).parent();
// do your stuff..
});
For getting the "invite object" you can attach a data attribute to the accept-invite button, this data attribute will contain a value that you will use to fetch the correct object, for an example:
<button type="button" id="inviteAcceptBtn" data-object-id="123">Accept invite</button>
Then you can get that "object-id" with simple jQuery:
$('#inviteAcceptBtn').on('click',function(){
var objectId = $(this).data('object-id');
// do your stuff..
});
There are probably a handful of other methods, as there are many techniques to do this.
Hope it helps a bit
There are multiple ways to do this:
Set the the username as one of the button's attributes.
assuming invite.initiator is the username that you intend to send
<button type="button" id="ButtonId" username={{invite.initiator}}>Accept invite</button>
In the javascript code you can access that element easily using attr method on this
url: '/api/send_invite/' + $( this ).attr("username"),
#sudomakeinstall2 : It should be better to add the data as a data-attrbute so :
<button type="button" id="ButtonId" username={{invite.initiator}}>Accept invite</button>
becomes
<button type="button" id="ButtonId" data-username="{{invite.initiator}}">Accept invite</button>
I am trying to submit my zipped formsets using Ajax. The code works perfectly when the request is not ajax. But whenever I am trying to implement Ajax, I am getting a ValidationError: [u'ManagementForm data is missing or has been tampered with']
My views:
def App(request):
lectures = Lecture.objects.all()
TopicFormSet = modelformset_factory(Topic, extra=0)
SummaryFormSet = modelformset_factory(Summary, extra=0)
tquery = Topic.objects.all()
squery = Summary.objects.all()
#saving formsets:
if request.method == 'POST' and request.is_ajax():
t_formset = TopicFormSet(request.POST)
s_formset = SummaryFormSet(request.POST) #formset instances
if t_formset.is_valid() and s_formset.is_valid():
t_formset.save() and s_formset.save()
zipped = zip(t_formset.forms, s_formset.forms) #saving them with new data
else:
return HttpResponse("not valid formsets, dude") # for testing purposes
else: #request=GET
t_formset = TopicFormSet(queryset = tquery)
s_formset = SummaryFormSet(queryset = squery)
zipped = zip(t_formset.forms, s_formset.forms)
return render (request, "app.html", {"lectures" : lectures, "zipped" : zipped, "t_formset" : t_formset, "s_formset" : s_formset})
And my Javascript code:
$(document).ready(function(){
$(".mygt").click(function(){ // it's a button
serializedData = $("#id_form-0-name").serialize(); // I didn't know how to "catch" all forms in formset so I am only serializing the first one
$.ajax({
url: "/app/",
type: "post",
data: serializedData,
csrfmiddlewaretoken:'{{ csrf_token }}',
success: alert(serializedData)
})
event.preventDefault();
});
});
P.S. I have also included csrf cookie in from this article: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax and {% csrf_token %} is present near the forms.
Edit: my html:
<form action = "http://127.0.0.1:8000/app/" method = "POST">
{% csrf_token %}
<!-- t_formset.management_form -->
{{ t_formset.management_form }}
<!-- t_formset.management_form -->
{{ s_formset.management_form }}
<!-- formsets -->
{% for topic, summary in zipped %}
<div id="topic">{{ topic }}</div>
<br>
<input type="submit" value="Submit" class="mygt" />
<br>
<div id="summary">{{ summary }}</div>
<br>
<input type="submit" value="Submit" class="mygt" />
{% endfor %}
The problem was that I did not know how to serialize all formset and I was only serializing the first field (for testing purposes). I was not aware of the fact that Django sends all formset and not just one field like I thought. So I replaced the
serializedData = $("#id_form-0-name").serialize();
with:
serializedData = $("form").serialize();
And the code works!
Did you include {{t_formset.management_form}} and {{s_formset.management_form}} in your template as described here?I had the same problem and i got the same answer here