I'm using ajax to submit a form, and it's working. But it's not working asynchronously. When I'm trying to upload files it uploaded successfully and then the page loads again. I want it to make asynchronously. In addition, I want to make a progress bar too. But things not working as I expected.
my forms.py
from django import forms
from .models import Comment
from .models import post
class UploadForm(forms.ModelForm):
class Meta:
model = post
fields = ('image', 'video', 'content',)
my views.py
def django_image_and_file_upload_ajax(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
form.instance.author = request.user
form.save()
return JsonResponse({'error': False, 'message': 'Uploaded Successfully'})
else:
return JsonResponse({'error': True, 'errors': form.errors})
else:
form = UploadForm()
return render(request, 'blog/upload.html', {'form': form})
and my upload.html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<main>
<div class="container">
<div class="row">
<div class="col-md-8 my-5">
<div class="content-section" style="padding:10px 20px">
<form
enctype="multipart/form-data"
id="id_ajax_upload_form" method="POST"
novalidate="">
<fieldset class="form-group">
{% csrf_token %}
<legend class="border-bottom mb-4"><i class="fas fa-feather-alt text-muted mr-2"></i>Create a post</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<input type="submit" />
</div>
</form>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
// form upload
$('#id_ajax_upload_form').submit(function(e){
e.preventDefault();
$form = $(this)
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (response) {
$('.error').remove();
console.log(response)
if(response.error){
$.each(response.errors, function(name, error){
error = '<small class="text-muted error">' + error + '</small>'
$form.find('[name=' + name + ']').after(error);
})
}
else{
alert(response.message)
window.location = ""
}
},
cache: false,
contentType: false,
processData: false
});
});
// end
where i get wrong?
Ok, Got it! But anyone know about how to add a progressbar will be helpful.
Related
In the castmascotvote view, everything is working when I'm authenticated, but not working otherwise. I have a print('entering not authenticated') right when it enters the else statement if the user isn't authenticated, but it never enters it, i'm boggled. I don't understand at all why it's not working. does anyone have any idea where I should start looking?
error message
The view didn't return an HttpResponse object. It returned None instead.
But I clearly have a HttpResponse object!
.html
<form class="mascotvoteform" action="{% url 'castmascotvote' mascot.id %}" id="{{mascot.id}}">
<div class="p-0"><h4>{{ mascot.name }} </h4> <p> by {{ mascot.author }} </p></div>
<div class="p-0"><img class="img-thumbnail" src="{{ mascot.image.url }}" style="width:250px;"></div>
<div class="row p-3">
{% if mascot.total_votes is 0 %}
<div class="col"><h5 id="mascotvotes{{mascot.id}}">0</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% else %}
<div class="p-0 col"><h5 id="mascotvotes{{mascot.id}}">{{ mascot.total_votes }}</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% endif %}
</div>
</form>
.script
$( document ).ready(function() {
$(".mascotvoteform").submit(function(e) {
{% if user.is_authenticated %}
e.preventDefault()
{% endif %}
let mascot_id = $(this).attr("id");
let url = $(this).attr('action');
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'mascot_id': mascot_id,
},
success: function(response) {
console.log('success', response)
$(`#mascotvotes${mascot_id}`).text(`${response['total_votes']}`)
};
},
error: function(response) {
console.log('error', response)
}
});
})
.views
def castmascotvote(request, mascot_id):
mascot = PoopMascot.objects.get(id=mascot_id)
user = request.user
if request.method == 'POST':
if user.is_authenticated:
if user in mascot.votes.all():
mascot.votes.remove(user)
else:
mascot.votes.add(user)
total_votes = mascot.total_votes()
data = { "total_votes":total_votes }
return JsonResponse(data, safe=False)
else:
print('entering user not authenticated')
messages.error(request, 'Please sign in to vote Poop Hero!')
return render(HttpResponseRedirect(reverse('user_login')))
else:
pass
I am trying to do a Django Blog in Class Based Views. They're proving very difficult to me anyway. I feel like I'm pretty close...I suspect it's creating a new one because I'm combining DetailView and trying to include an UpdateView in my page. I'm overriding POST on the DetailView...and perhaps that's why when I try to do my Update of the comment the overriden Post on DetailView is overriding that action?
Here's my code....
HTML...
<!DOCTYPE html>
<form method='POST' class="comment-form">
{% csrf_token %}
<div class="spacer284">
{{ form.comment }}
</div>
<button class="button7" type="submit">Submit</button>
</form>
<div class="spacer285">
{% include 'suggestion_comments.html' %}
</div>
</div>
{% endblock %}
Note that I'm doing an include so that I can loop through the comments more easily...
Here's the include template...
{% if suggestion_comments %}
<h2>Comments</h2>
{% for comment in object.suggestion_comments.all %}
<div class="spacer291">
<p>{{ comment.author }} {{ comment.created_on }}</p>
<p class="spacer290">{{ comment.comment }}</p>
<div class="spacer289">
<div class="upvote-comment-count">{{ comment.total_comment_upvotes }}</div>
<div class="hide-delete">
<button type="button" class="button6" data-href="{% url 'Suggestions:suggestion_comment_like' comment.id %}">Like</button>
</div>
<div class="hide-delete">
<button type="button" class="button2" data-href="">Reply</button>
</div>
{% if comment.author == request.user %}
<button type="button" class="button4" id="{{ comment.id }}" pk="{{ object.pk }}" href="{% url 'Suggestions:suggestion_comment_edit' object.pk comment.id %}">Edit</button>
<div class="spacer159" id="hide_payment" style="display:none;">
<input name="comment" id="commentInput" value="{{ comment.comment }}" class="name"/>
<button class="button7">Submit</button>
</div>
<div class="hide-delete">
{% if user.userprofile.eDirector_queue_delete_confirm == "Yes" %}
<button type="button" class="button5" data-href="{% url 'Suggestions:suggestion_delete' comment.id %}">Delete</button>
{% else %}
<button type="button" class="button3" data-href="{% url 'Suggestions:suggestion_delete' comment.id %}">Delete</button>
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<h2>No Comments Yet</h2>
{% endif %}
I'm attempting to use AJAX to do a replace...
$(document).on('submit', '.comment-form', function(e) {
e.preventDefault();
var $this = $(this);
$.ajax({
type: "POST",
url: $this.data("href"),
data: $this.serialize(),
dataType: "json",
csrfmiddlewaretoken: "{{ csrf_token }}",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(response){
console.log("so far");
$('.spacer285').html(response['form']);
$(".comment-form")[0].reset();
$('.spacer288').empty('spacer288');
},
error: function (request, status, error) {
console.log(request.responseText);
showAjaxFormErrors(JSON.parse(request.responseText));
},
});
});
$(document).on('click', '.button7', function(e) {
e.preventDefault();
console.log("working123");
var $this = $(this);
var comment = $('#commentInput').val();
console.log(comment);
$.ajax({
type: "POST",
url: $this.data("href"),
data: { comment: comment},
csrfmiddlewaretoken: "{{ csrf_token }}",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data){
console.log(data);
$('.comment-form1').html(data);
},
});
});
My DetailView...
class SuggestionDetailView(LoginRequiredMixin,DetailView):
model = Suggestion
context_object_name = 'suggestion_detail'
template_name = 'suggestion_detail.html'
def get_context_data(self, **kwargs):
context = super(SuggestionDetailView, self).get_context_data(**kwargs)
attachments = SuggestionFiles.objects.filter(suggestion=self.object.pk).all()
form = SuggestionCommentForm()
suggestion_comments = SuggestionComment.objects.filter(suggestion_id=self.object.pk).order_by('-created_on').all()
context['attachments'] = attachments
context['form'] = form
context['suggestion_comments'] = suggestion_comments
return context
def post(self, request, *args, **kwargs):
form = SuggestionCommentForm(request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.suggestion = self.get_object()
new_comment.save()
self.object = self.get_object()
context = self.get_context_data(object=self.object)
html = render_to_string('suggestion_comments.html', context, request=self.request)
return JsonResponse({'form': html})
else:
form_errors = form.errors.as_json()
response = HttpResponse(form_errors, status=400)
response['content_type'] = 'application/json'
return response
MyCommentUpdateView...
class SuggestionCommentUpdateView(LoginRequiredMixin, UpdateView):
model = SuggestionComment
fields = ["comment"]
def form_valid(self, form):
form.instance.suggestion_id = self.kwargs["pk"]
return super().form_valid(form)
And my URLs...
path("a7900f81-b66a-41ea-afc2-d7735e6d4824/suggestion_detail/<uuid:pk>/suggestion_comment_edit/<int:id>",views.SuggestionCommentUpdateView.as_view(), name='suggestion_comment_edit'),
path("a7900f81-b66a-41ea-afc2-d7735e6d4824/suggestion_detail/<uuid:pk>/",views.SuggestionDetailView.as_view(), name='suggestion_detail'),
This is all almost working....My issue is when I click on the edit button and attempt to edit the comment....it works...and updates the database...but it's adding a new updated comment instead of just editing the existing comment. Thanks in advance for any thoughts on what I might be doing wrong.
I have a form that I am trying to implement with Ajax, after inputing some content on the textbox, when I click on the sumbit button using my mouse, everything works fine (page didnt refresh, data posted on database, and new data displayed on the page). But when I try to submit data by pressing enter, the page is displaying only the serialized data from my form (nothing more, html file do not work)and it says in the console:
Resource interpreted as Document but transferred with MIME type application/json: "http://localhost:8000/try/".
current page looks exactly like this after pressing enter button(nothing more):
{"task": {"id": 52, "todo": "wws", "author": 1, "completed": false}}
these are the data that came from my form.
this is my views.py
class TodoList(View):
def get(self, request):
todo_list = ToDo.objects.filter(author_id=request.user.id)
form = AddTodo()
context = {
'todo_list': todo_list,
'form': form,
}
return render(request, 'trylangto/try.html', context)
def post(self, request):
form = AddTodo(request.POST)
if form.is_valid():
form.instance.author_id = request.user.id
new_form = form.save()
return JsonResponse({'task': model_to_dict(new_form)}, status=200)
else:
return redirect('trylang:todo-list')
return redirect('trylang:todo-list')
this is my main.js:
$(document).ready(function(){
$("#createbutton").click(function(){
var formdata = $("#addtodoform").serialize();
$.ajax({
url: $("#addtodoform").data('url'),
data: formdata,
type: 'post',
success: function(response){
$("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">×</span></button></div></div>')
}
});
});
});
and here is my template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% if user.is_authenticated %}
<div class="media content-section">
<form class="media-body pt-3" method="POST" id="addtodoform" data-url="{% url 'trylang:todo-list' %}">
{% csrf_token %}
<legend><h5>add new tasks</h5></legend>
<fieldset class="form-group ">
{{ form|crispy}}
</fieldset>
<button class="btn btn-outline-info float-right" type="button" id="createbutton">add</button>
</form>
</div>
{% endif %}
<div id="tasklist">
{% for task in todo_list %}
<div class="card mb-1" >
<div class="card-body">
{{task.todo}}
<button type="button" class="close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
UPDATE: I am including my models.py just in case
class ToDo(models.Model):
todo = models.CharField(max_length=500)
date_posted = models.DateTimeField(default=timezone.now, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
completed = models.BooleanField(default=False)
this is what I get on the console when I use console.log(formdata):
csrfmiddlewaretoken=N91OUGSd6kBFkB1E2DMZuMW6qJD7cc3frPprwGMLTuupcg6PKYtt44jA4z5Lx6xX&todo=this%20is%20the%20content%20of%20my%20textbox
You don't need model_to_dict. So, try:
if form.is_valid():
form.instance.author_id = request.user.id
new_form = form.save()
return JsonResponse({'task': new_form}, status=200)
else:
return redirect('trylang:todo-list')
return redirect('trylang:todo-list')
EDIT
You are submitting the form not through ajax. When you click button it was submitting the form. So, e.preventDefault() should do the job.
$(document).ready(function(){
$("#createbutton").click(function(e){
e.preventDefault(); <--- You were missing this
var formdata = $("#addtodoform").serialize();
$.ajax({
url: $("#addtodoform").data('url'),
data: formdata,
type: 'post',
success: function(response){
$("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">×</span></button></div></div>')
}
});
});
});
and at page i'm not see csrdI try after receiving one form to get another
views.py
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string( 'registers/endreg.html', {'form': NameForm1() } ) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
def endreg(request):
if request.method == 'POST':
form = NameForm1(request.POST)
if form.is_valid():
code_use = form.cleaned_data.get("key")
try:
user = Registration.objects.get(code=code_use)
user.verification = True
user.save()
messages.warning(request, u'thanks.')
except:
messages.warning(request, u'error.')
else:
form = NameForm1()
return render(request, 'registers/endreg.html', {'form': form})
and ajax
$(document).ready(function()
{ $("#my_form").submit(function(event)
{ event.preventDefault();
$this = $(this);
$.ajax({
type: "POST",
data: $this.serialize(),
success: function(data)
{ console.log(data);
$this.html(data.form1);
},
error: function(data)
{ console.log(data);
}
});
});
});
I am facing a CSRF token missing or incorrect problem. Because it is not transferred to form 2. how can I transfer this token to a new form
detatil.html it's html first page
{% extends 'base.html' %}
{% load i18n %}
{% block content%}
<div class="main-form">
<form action="" method="post" autocomplete="off" id="my_form">
{% csrf_token %}
<div class="contact-form" >
<h1>{%trans 'Регистрация' %}</h1>
<div class="txtb">{{form.fio.label}} {{form.fio}}{{form.fio.help_text}}</div>
<div class="txtb"> {{form.purpose.label}}{{form.purpose}}</div>
<div class="container" id="none">{{form.tso.label}}{{form.tso}}</div>
<div class="txtb">{{form.phone.label}} {{form.phone}}{{form.phone.help_text}}{{form.phone.errors}}</div>
<div class="txtb"> {{form.number_car.label}}{{form.number_car}}</div>
<div class="txtb"> {{form.date_visit.label}}{{form.date_visit}}</div>
<div class="txtb"> {{form.captcha.label}}<br>{{form.captcha}}{{form.captcha.errors}}</div>
<input type="submit" value="{%trans 'send' %}" class="btn" id="btn">
</div>
</form>
</div>
{% endblock %}
it's html secon page endreg.html
{% load i18n %}
{% block content%}
<form action="" method="post" autocomplete="off" >
{% csrf_token %}
<div class="verification" >
<div class="ver">
{{form}}
</div>
<input type="submit" value="{%trans 'send' %}" class="btn1" >
</div>
</form>
{%endblock%}
csrf token is on two pages, but when I look at the code in the browser, it does not appear when I add 2 forms using ajax
since you are using render_to_string, you need to pass request object to render_to_string. You can acheive it by:
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'ver code'
message = user_code
phone = request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
Registration.objects.create(fio=request.POST['fio'],mail=request.POST['mail'])
send_mail(subject, message,settings.EMAIL_HOST_USER,[mail],fail_silently=False)
return JsonResponse({ 'form1': render_to_string('registers/endreg.html', {'form': NameForm1()}, request=request) })
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
I have a Formset that allow so uploadoad multiple images with a description:
def bilddokumentation_form(request, auftrag):
auftrag = Auftrag.objects.get(id=auftrag)
BilddokumentationFormSet = formset_factory(BilddokumentationForm, extra=1)
formset = BilddokumentationFormSet(request.POST or None, request.FILES or None)
if formset.is_valid():
for form in formset.cleaned_data:
name = form['name']
bild = form['bild']
Bilddokumentation.objects.create(
name=name,
bild=bild,
auftrag=auftrag,
user=request.META['USER'],
)
else:
print(formset.errors)
return render(request, 'auftragsverwaltung/bilddokumentation_add.html', {'item_forms': formset, 'auftrag': auftrag})
But only the first form will be saved. The second form doesn't appear in the cleaned_data.
This is the template:
<script type="text/html" id="item-template">
<div id="item-__prefix__">
{{ item_forms.empty_form }}
</div>
</script>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ item_forms.management_form }}
<div id="items-form-container">
{% for item_form in item_forms %}
<div id="item-{{ forloop.counter0 }}">
{{ item_form.id }}
{{ item_form.as_p }}
</div>
{% endfor %}
</div>
weiteres Bild hinzufügen
<input type="submit" class="btn btn-primary" value="Bilder hinzufügen">
</form>
<script>
$(document).ready(function() {
$('.add-item').click(function(ev) {
ev.preventDefault();
var count = $('#items-form-container').children().length;
var tmplMarkup = $('#item-template').html();
var compiledTmpl = tmplMarkup.replace(/__prefix__/g, count);
$('div#items-form-container').append(compiledTmpl);
// update form count
$('#id_item_items-TOTAL_FORMS').attr('value', count+1);
// some animate to scroll to view our new form
$('html, body').animate({
scrollTop: $("#add-item-button").position().top-200
}, 800);
});
});
</script>
And the form:
class BilddokumentationForm(ModelForm):
class Meta:
model = Bilddokumentation
exclude = ['user', 'datum', 'auftrag']
widgets = {
'name': Textarea,
}
I can see that the second form is in the POST data, but it wont appear in the cleaned_data.
What would be the correct way to do it? And why does Django discard the second form?