Reputation: 564
I have googled around and it seems like there are many possibilities for php. But I haven't found anything good solution for django. I saw some people using client side javascript code for this, but I just don't get how to fix this. Problem I;m having is:when user writes a post, and click submit button fast twice before new page gets loaded then two posts will be made. Here's my code, thanks in advance. my html
<form id="post_form" method="post" action="/add_post/" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="submit" value="submit">
</form>
my views.py
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self, form):
self.object = form.save(commit=False)
# any manual settings go here
#self.object.category = Category.objects.filter(category__in=categories).all()
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(PostCreateView, self).dispatch(request, *args, **kwargs)
Edit: I changed it to like this
{% block content %}
<div class="col-sm-5">
<form id="post_form" method="post" action="/add_post/" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" id="button" name="submit" value="올리기">
</form>
</div>
<div class="col-sm-4" style="width:400px; height:250px; border:1px solid black;">
<h3>rule</h3>
</div>
<div class="col-sm-3" style="width:420px; height:750px; border:1px solid black;" >
<h3>ad</h3>
</div>
{% endblock %}
<script>
jQuery('input[name=submit]').on('click', function(){
if(jQuery(this).hasClass('active')){
return false;
}
else{
jQuery(this).addClass('active');
}
});
</script>
{% include 'footer.html' %}
Final Edit: hope this is right? any suggestion?
import datetime
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self, form):
self.object = form.save(commit=False)
# any manual settings go here
#self.object.category = Category.objects.filter(category__in=categories).all()
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
if not hasattr(self.request.session['last_submitted']):
self.request.session['last_submitted'] = datetime.datetime.now()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
else:
delta = datetime.datetime.now() - self.request.session['last_submitted']
if delta.seconds < 60: # assume allow re-submit after 60 seconds
return http.HttpForbidden() #or some other better message??
else:
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(PostCreateView, self).dispatch(request, *args, **kwargs)
Edit with the solution provided
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self,form):
if not hasattr(self.request.session['last_submitted']):
last_submitted = pickle.dumps(datetime.datetime.now())
self.request.session['last_submitted'] = last_submitted
save_it = True
else:
last_submitted = pickle.loads(self.request.session['last_submitted'])
delta = datetime.datetime.now() - last_submitted
save_it = (delta.seconds > 60) # assume allow re-submit after 60 seconds
if save_it:
self.object = form.save(commit=False)
# any manual settings go here
#self.object.category = Category.objects.filter(category__in=categories).all()
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
else:
# consider redirect as usual, if the user just clicked twice by mistake
return self.form_invalid(form) # or Http error code
Upvotes: 2
Views: 2855
Reputation: 3658
If this is the buttton:
<input type="submit" name="submit" value="submit" id="preventDouble">
With jQuery:
$("#preventDouble").on("submit",function(){
$(this).unbind("submit");
$(this).on("submit",function(){return false;});
};
After the first submit, jQuery will attach an event that will cancel further submits.
Note that this event does not check if the form was actually successfully submited to the server.
This may answer your question, but it's a safer and better approach to track multiple submits on the server, e.g. adding a "last_submitted" attribute to the session, and prevent further submits if datetime.datetime.now is less than 1 minute from session.last_submitted:
import datetime
import pickle
def form_valid(self,form):
if not hasattr(self.request.session['last_submitted']):
last_submitted = pickle.dumps(datetime.datetime.now())
self.request.session['last_submitted'] = last_submitted
save_it = True
else:
last_submitted = pickle.loads(self.request.session['last_submitted'])
delta = datetime.datetime.now() - last_submitted
save_it = (delta.seconds > 60): # assume allow re-submit after 60 seconds
if save_it:
self.object = form.save(commit=False)
# any manual settings go here
#self.object.category = Category.objects.filter(category__in=categories).all()
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
else:
# consider redirect as usual, if the user just clicked twice by mistake
return self.form_invalid(form) # or Http error code
Edit
import datetime
import pickle
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self,form):
if not hasattr(self.request.session['last_submitted']):
last_submitted = pickle.dumps(datetime.datetime.now())
self.request.session['last_submitted'] = last_submitted
save_it = True
else:
last_submitted = pickle.loads(self.request.session['last_submitted'])
delta = datetime.datetime.now() - last_submitted
save_it = (delta.seconds > 60) # assume allow re-submit after 60 seconds
if save_it:
self.object = form.save(commit=False)
# any manual settings go here
#self.object.category = Category.objects.filter(category__in=categories).all()
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
else:
# consider redirect as usual, if the user just clicked twice by mistake
return self.form_invalid(form) # or Http error code
Upvotes: 1
Reputation: 434
Not sure your project is using jquery lib or not. if it does try following:
jQuery('input[name=submit]').on('click', function(){
if(jQuery(this).hasClass('active')){
return false;
}
else{
jQuery(this).addClass('active');
}
});
What this will do is check if button is already clicked or not. If it does it won't resubmit the page. If you are not using any client side library then i can change it to Native js.
Upvotes: 0