Stopping multiple view calls generated via frenzied button clicks (Django app) - django

I'm uploading an image file in a basic Django web app. There's an upload button in the html template wrapped around by a form tag. Once the upload button is pressed, the underlying view takes over and processes image upload.
In the Chrome browser of my colleague's Macbook, pressing upload multiple times really quickly manages to call the underlying function multiples times too. I end up getting a plethora of copies of the image being uploaded.
However, this isn't replicatable in my own environment's Firefox (Ubuntu OS). Seems this issue is browser sensitive?
In any case, how do I cut off this code behavior? If the user goes into a click frenzy, I don't want multiple images to go up. Can someone guide me how to handle this in Django? I would prefer a non-JS, server solution too.
Note: Let me know if you need to see my related code.

Many people faces this issue. If the submit button called 3 times wihtout waiting to refresh the browser, it will gonna add 3 times.To prevent that you can use jQuery.
For example on form submit you can show the loader or disable the submit button,
$('#login_form').submit(function() {
$('#gif').css('visibility', 'visible');
or
$('#button').prop('disabled', true);
});
Edit for server side implementation:
I do not suggest this for user interface point of view but if you can also valid submits using sessions or cookies.Generate random token in your view and set this in your form as hidden input.
for e.g.,
def checkform(request):
form = ExampleForm(request.POST or None)
randomtoken = #generate random token here and set in session or cookie
if form.is_valid():
# check_token here
session_value == request.POST.get('your_hidden_token')
# if matched than change the random token and save your data else do your restriction processing
render ( request,'template.html',context={ 'form':form,'randomstring':randomstring } )

Related

Issue with POST email, returning to same page, templates and httpresponse

First of all, I only started using Django a week ago... so pretty new :).
I have a one page website. At the bottom there is a contact form. I am using different components for the website, so for the contact form I have 'contact.html' which is loaded into index.html via {& include ... &}. When someone sends a message via contact form, after click send, the user returns to the same page but with a thank you message instead of the contact form (see screenshot).
The issue is that I need to 'kill' the process going on underneath because if I reload the page a message pops and if I resubmit, email gets resend again (see screenshot).
I have had a look at httpresponse but I am unsure how to replicate the same process. Anyone could help?
This is a screenshot of contact.html and views.py
Two things.
I would first consider using a front end framework such as react. (will make your life easier)
Secondly, your code seems fine, you are sending the email twice because you are submitting the form twice.
perhaps redirect the user to a different page upon submission. there is no need to reload the page yourself.
I would have a form, then a confirmation page.
Better yet, write an api, and upon response from the server simply create a popup saying success/fail etc...

Django: CSRF middleware and mixed POST/GET forms

I would like to crate a form whith two submit buttons: Save, let's say, and Back to edit. (The form is meant for a preview / confirm view of stuff that is currently being edited).
For obvious reasons the Save button has a formaction attribute with value post and the other button get. For the post action to work, I include the usual csrfmiddlewaretoken in the form.
So far all works well, the only problem is that the csrfmiddlewaretoken value is now included in the GET requests (which seems to be discouraged for security reasons).
Currently I add some custom javascript that finds all submit buttons with get action and adds a click handler that removes the csrfmiddlewaretoken from the field before submit. This seems a rather wierd and roundabaout way to do things.
Question: Is there a better / more standard / more stable way to handle this situation?
Edit: Why do I want to use get requests for some form actions?
Well, I would like to stick to the rule to use POST requests (only) for requests that change data (and in that case respond with a redirect).
As an example, think of a form where the user can edit ("page A") some fields, and then can press "preview" (a GET action), which leads "page B" where the same form is presented, but readonly, with a preview image generated by the system. If the user is happy, they can press "save" (a POST action) which will actually save the data, or they can press "back" (a GET action, similar to the Browser's back button), to continue editing the data. I would not be happy to implement this "Back" operation as POST, as this messes up the interaction with the actual Browser back button etc.
In this simple example, one could of course ask the user to use the browser back button instead of a form button, or (probably?) use javascript to simulate a browser back. But with slightly more complicated flow control a simple "back" is not an option.
The problem is that you send GET request from the form that contains your CSRF token. I would rather recommend PUT request than GET request. The CSRF token value is not exposed on the URL because the PUT request allows the body value to be passed.
About HTTP PUT method

django POST [Legitimacy]

Lets say I have a web application that displays 2 random buttons on each session, and I want the user to click on 1 button or the other. If a button is clicked, I want to increment the score for that button. However, the user has no control on what 2 buttons are presented each time and there are thousands of possible buttons.
If I create a view to increment the button, how would I be sure that the user wont just manually go to that view through the browser.
My thoughts are that you need to create a form and have users POST to a certain address, but how do you know that the user didn't just send a post request through AJAX to increment the button and that the user actually received that button from the randomized session with 2 buttons.
How would I handle this in Django is there documentation detailing how Django specifically supports this?
EDIT: Or do you have to create a unique session ID for each button selecting session and check each button click against the unique session ID.
Create a session variable to track the button they see, like:
def button_display_view(request):
# ...lots of cool logic
session['buttons_shown'] = [button_1_primary_key, button_2_primary_key]
return response
Then, in your button click view, ensure that the button clicked was in the list of buttons that they were shown. The user will have zero knowledge of your session variable, nor be able to edit it, much like he/she can't when you use session variables to track authentication, etc.
If you're building a multivariate testing system (or even an AB testing system), it might be worth checking out this MVT app for ideas.

How to restrict users from going back to the previous page with the browser "back button" (redirect to a different page, instead)?

I am working on a site that would allow users to post some data. To successfully add a new post, the users need to go through three states: Form -> Preview -> Posted page. I want to restrict the users from going back to the Preview page with the browser "back button" once they have already reached the Posted page (instead, they should be redirected to the empty Form page). How can I implement this behaviour in Django?
I am not sure how you get this desired behavior from Django as you have limited control over the user's browser. However, in Javascript you can use:
window.location.replace(url);
which will remove history, thus preventing the back button from working.
See this stack overflow question about window location:
What's the difference between window.location= and window.location.replace()?
An idea: from your preview page, use AJAX to submit and if all is successful, window.location.replace to your posted page.
I can't speak for how to deal with this using browser technologies but with django you could just set a flag in the session.
# posted_page view
request.session['posted_page_visited'] = True
# preview_page view
if request.session.get('posted_page_visited'):
del request.session['posted_page_visited']
return http.HttpResponseRedirect("form_page")
Using js (window.location.replace(url)) doesn't fulfill this requirement because "replace url" will just replace the page with another one,Ex: if form flow goes from page1 to page2 then page3 then page4 and (window.location.replace(url)) is used in page2 (window.location.replace(page4);) then page3 will never be visited!! moreover user will still be able to go back in the same forward path meaning from page4 to page2...etc
the good thing, you can solve it by using Django session as shown below assuming users will be able to go back and forth as long as form not yet saved, and once its saved they can't go back anymore:
in page1/view function where first part of form is issued create session varaible:
in view1.py
def view1(request)
.
.
.
request.session['forward'] = True
return redirect(....)
in view2.py:
def view2(request):
if not request.session['forward']:
return redirect(..Select whatever page you want to redirect users to it..)
the same in rest of pages views..
in the last page/view where after saving the form, reset the variable:
request.session['forward'] = False
return redirect(..Select whatever page you want to redirect users to it..)
hopes its clear enough
django's form wizard should do what you want:
How it works
Here’s the basic workflow for how a user would use a wizard:
The user visits the first page of the wizard, fills in the form and submits it.
The server validates the data. If it’s invalid, the form is displayed again, with error messages. If it’s valid, the server saves
the current state of the wizard in the backend and redirects to the
next step.
Step 1 and 2 repeat, for every subsequent form in the wizard.
Once the user has submitted all the forms and all the data has been validated, the wizard processes the data – saving it to the
database, sending an email, or whatever the application needs to do.

Facebook like button - how to prevent activity stream from getting into the user's wall?

Can someone please help me out as to how I can completely prevent the user's activity stream from posting back into their wall after they liked a linked? Because, I really find that to be annoying. Afterall, mine is an application that needs to be integrated into an image gallery viewer serving more than 7.5K photos each with its own like button.
If this seems impossible, is there a way to specifically set an image as thumbnail, description, etc as is with the cases of feed and send buttons?
Because, my application is purely dynamic in nature built out of 100% Javascript where more than 80% of its contents are generated by using Ajax calls under a static single URL.
As a result, the like button activity stream always end up pulling the wrong image and descriptions than desired(but this is not so for feed and send buttons),
Thank you
No, you won't have control over not sending items to peoples activity feeds when they click like, unless your domain gets blocked for spam. You would need to create a dynamic url or hashbang url for each independent image and when those images are requested the page hosting it would need to have the proper open graph meta tags sets for thumbnail image, description, etc. Then for each like button in the gallery, you would need to set the href property to this url.