My form resubmits every time I refresh the page. I want to send context with my render
if request.method == 'POST' and 'search_form' in request.POST:
rol = request.POST['rol']
group = request.POST['group']
national_number = request.POST['national_number']
phone_number = request.POST['phone_number']
users = MyUser.objects.filter(Q(group__name=group)|Q(role__name=rol)|Q(national_number=national_number)|Q(phone_number=phone_number))
return render(request,'deletuser.html',locals())
If you directly render a page as the result of a POST, then refreshing that page will resubmit the form, because that's how you got there.
The usual way to avoid this is to issue an HTTP redirect after a POST, instead of rendering content directly. Then the user ends up on a page via GET, which can be refreshed without problems.
You can google search for "redirect after post" to get more details.
Related
I have a book page. On this page is the button "In favorite". If the user clicks on the button and is authenticated, it will use addBookmark view to add a new object into the database(and just reload the book page). However, if the user isn't authenticated, it'll redirect to the login page firstly.
#login_required
def addBookmark(request, slug):
book = Book.objects.get(slug=slug)
if BookMark.objects.filter(user=request.user, book=book).exists():
bookMark = BookMark.objects.get(user=request.user, book=book)
bookMark.delete()
return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
newBookMark = BookMark.objects.create(user=request.user, book=book)
newBookMark.save()
return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
The problem: When a user is redirected to the login page, the next URL will just add a new object in db and reload the page, but this is the login page. How can I redirect users back to the book page if the user isn't authenticated firstly?
Firstly, remove #login_required.
You can redirect user manually like this:
if not request.user.is_authenticated:
return redirect("bookmark_url")
How can I stop Flask from re-adding form data to database on refresh?
My form.html sends data to approved.html like so:
if request.method == 'POST':
element = db_name(request.form.get('element'))
db.session.add(element)
db.session.commit()
else:
return redirect(url_for('home'))
return render_template('approved.html', current=element)
This so I can display the data from the form and let the user know entry has been added. But the problem is whenever I refresh approved.html which displays the form data, another copy of this entry is added to the database.
This happens because the browser stores the state of the last request and refreshing will re-submit the form, leading to another entry in your database. This is also why it's normal practice to redirect on the server-side after successful form submission. See Preventing POST on reloading a form and here
What you need to do is to successfully handle a successful form request and then redirect the user to a fresh state.
So something like this
return redirect(url_for('success'))
can be added instead of the render_template function which will then be redirected to the assigned function; there you can call the render_template of your choice.
I have created django form.py file :
from django import forms
from models import ResumeModel
class ResumeForm(forms.ModelForm):
username = forms.CharField(max_length = 200)
first_name = forms.CharField(max_length = 200)
last_name = forms.CharField(max_length = 200)
fathers_name = forms.CharField(max_length = 200)
email = forms.EmailField(required=True, label='Your e-mail address')
message = forms.CharField(widget=forms.Textarea)
class Meta():
model = ResumeModel
fields =('username','first_name','last_name','fathers_name','email','message')
views.py :
def save(request):
if 'submit' in request.POST:
form = ResumeForm(request.POST)
if form.is_valid():
form.save()
form = ResumeForm()
return render(request, '/success/', {'form': form})
else:
form = ResumeForm()
args = {}
args.update(csrf(request))
args['form'] =form
return render_to_response('create.html',args)
urls.py:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^save/', 'Resume.views.save'),
url(r'^success/$', TemplateView.as_view(template_name='success.html')),
)
Now all is working fine. problem is that as i submit form it moves to success page and when i go back to previous page that is /save/ page it holds all the values in fields that i submitted. How to clear the fields if i press back button to go back to that form page having url as "/save/ "
This is about the browsers behaviour. Browser shows u the page in its cache instead of calling a new page.
U may workaround this by using javascript.Unfortunately browser also dont run the javascript codes again.
But u may try :
$(window).bind("pageshow", function() {
// Clean form values
});
by JQuery
This is a browser implementation detail. You might be able to hack your way around it with JavaScript or break the cache etc. The subject is discussed in this stackoverflow question.
However a nicer UI approach might be to use AJAX to POST a serialised version of the form. If you successfully validate and process that form in your view (inserting a new row into your resume model table etc), you could then send a JSON response which might invoke some JavaScript to clear the form fields (maybe using .reset()). The user is then free to submit another form easily if that is the requirement.
Also note it is recommended that you use a HttpResponseRedirect after a successful POST (you have a render() response at the moment). This stops the users re-submitting the form again and potentially duplicating rows in your databases etc.
Hi I added reCAPTCHA to a page so far that it can verify a client. Now I want a more graceful failure when isHuman = Falsewith a redirect to the form page in such case with a message on the form page that reCAPTCHA failed. Can you inform what to do rather than just outputting "captcha failed?" so that it can redirect to the form page with Google App Engine's request handler? Here's my code:
def post(self, view): #edit
challenge = self.request.get('recaptcha_challenge_field')
response = self.request.get('recaptcha_response_field')
remoteip = os.environ['REMOTE_ADDR']
cResponse = captcha.submit(
challenge,
response,
CAPTCHA_PRV_KEY,
remoteip)
if cResponse.is_valid==True:
isHuman=True
else:
isHuman=False
self.response.out.write('captcha failed')
return
If you are just looking for a way to redirect back to your original posting page you can use:
self.redirect('your_url')
You could also include a GET variable in the url so that the page is aware that the CAPTCHA failed.
I'm trying to have my form submit to a route which will validate the data then redirect back to the original route.
For example:
User loads the page website.com/post
Form POSTs the data to website.com/post-save
User gets redirected back to website.com/post
Pyramid is giving me some troubles doing this.
Here's my slimmed down views.py
def _get_link_form(post_data):
""" Returns the initialised form object """
return LinkForm(post_data)
def home_page(request):
form = _get_link_form(request.POST)
return {'form' : form}
def save_post(request):
""" form data is submitted here """"
form = _get_link_form(request.POST)
if not form.validate():
return home_page(request, form)
This is the code I've been playing around with. Not only does it not work, it also feels messy and hacked up. Surely there's a simpler way to 'redirect after-POST' in Pyramid?
Your problem is most easily solved by simply POSTing to the same URL that your form is shown at, and simply redirecting the user away from the page when the POST is successful. That way until the form is successfully submitted you do not change URLs.
If you're just dying to POST to a different URL, then you need to save the data using sessions, since you're obviously handling the form data between requests.
Typically if you want to be able to handle errors in your forms you would use a session and flash messages. To do this you simply add a location for flash messages to appear in your base template and setup session support using something like pyramid_beaker.
Assuming your home page is setup at the 'home' named-route:
from pyramid.httpexceptions import HTTPFound
def myview(request):
user = '<default user field value>'
if 'submit' in request.POST:
user = request.POST.get('user')
# validate your form data
if <form validates successfully>:
request.session.flash('Form was submitted successfully.')
url = request.route_url('home')
return HTTPFound(location=url)
return {
# globals for rendering your form
'user': user,
}
Notice how if the form fails to validate you use the same code you did to render the form originally, and only if it is successful do you redirect. This format can also handle populating the form with the values used in the submission, and default values.
You can loop through the flash messages in your template of choice using request.session.peek_flash() and request.session.pop_flash().
route_url supports mutating the query string on the generated url as well, if you want to flag your home page view to check the session data.
You can obviously just pass everything in the query string back to the home page, but that's a pretty big security vulnerability that sessions can help protect against.
The Pyramid documentation has a particularly on-point section with the following example:
from pyramid.httpexceptions import HTTPFound
def myview(request):
return HTTPFound(location='http://example.com')
I do this like so:
from pyramid.httpexceptions import HTTPCreated
response = HTTPCreated()
response.location = self.request.resource_url( newResource )
return response
This sends the HTTP Created code , 201
The Pyramid documentation has content about Redirect, you can see more information in below link :
Pyramid documentation
import pyramid.httpexceptions as exc
raise exc.HTTPFound(request.route_url("section1")) # Redirect
Edited:
Actually you can do that on client side with Javascript, first you should send particular response to client side(either with flashes some data or return Response object):
window.location = '{{ request.route_path("route_name") }}';
Assuming your homepage is the default view of your pyramid web app, you can do:
def _get_link_form(post_data):
""" Returns the initialised form object """
return LinkForm(post_data)
def home_page(request):
form = _get_link_form(request.POST)
return {'form' : form}
def save_post(request):
form = _get_link_form(request.POST)
if not form.validate():
from pyramid.httpexceptions import HTTPFound
return HTTPFound(location=request.application_url)
Basically you need to know how the home_page view was "added" to your Configurator. If your homepage actually lives at /few/levels/deep/homepage then a redirect might look like this:
return HTTPFound(location=request.application_url + '/few/levels/deep/homepage')
A clean way is using the "overload" provided by pyramid for different request types, por example, you can decorate your methods this way:
#action(request_method='GET',
renderer='mypackage:/templates/save.mako',
name='save')
def save(request):
''' Fill the template with default values or leave it blank'''
return {}
#action(request_method='POST',
renderer='mypackage:/templates/save.mako',
name='save')
def save_post(request):
""" form data is submitted here """"
# process form
In the HTML, you must call the action form, like
<form method="POST" id="tform" action="${request.route_url('home', action='save')}">
This way, one method is processed when the method POST is used, and the other when the GET is used. The same name, but two implementations.