How to hide success page in Django - python

I'd like to know if anyone knows:
For example, I have a form that user fills in, and when he submits, the page will redirect to "thank you" page. Everything works fine. In urls.py I had this line pointing that the page exists:
url(r'^thankyou/$', 'render_form'),
But then, when I type in url mysite.com/thankyou/, the page "Thank you" appears... But I need it to appear only when I submit a form and hide it when user tries to open it directly.
Please help. Thanks in advance!

You could put something in the session in your form handling view before redirecting, and check it in the thank-you URL: if it's not there, then return a 403 error. Something like:
def form_handling_view(request):
if request.POST:
form = MyForm(request.POST)
if form.is_valid():
... handle the form ...
request.session['form_posted'] = True
return redirect('thank_you')
def thank_you(request):
if not request.session.pop('form_posted', False):
return HttpResponseForbidden('not permitted')
... render thank_you page ...
Note I'm using pop in thank_you to ensure that the key is deleted from the session no matter what.

Related

Django: User Reporting Some URL on Website

So i'm trying to build something, so that users would be able to report something on site. Here's the model,
class Report(models.Model):
reporting_url = models.URLField()
message = models.TextField()
I created Form for this Model including 'message' field only because 'reporting_url' is something it needs to populate by itself depending upon the specific page from where user has clicked "Report" button.
def report(request):
url_report = ???
if request.method == 'POST':
form = ReportForm(request.POST or None)
if form.is_valid():
new_form = form.save(commit=False)
new_form.reporting_url = url_report
new_form.save()
I was wondering How can I pass the specific url to 'reporting_url' field in form depending on the Page from where user has clicked "Report" button? (Much like s we see on social Networks).
Am I doing this correctly, Or is there a better way for doing this?
Please help me with this code. Thanks in Advance!
If there is a report button on that specific page then I believe you could write custom context processor.
More info: Django: get URL of current page, including parameters, in a template
https://docs.djangoproject.com/en/1.11/ref/templates/api/
Or maybe just write it directly in the views.py in your function and set
url_report = request.get_full_path()
I think you can use the form on the same page of the URL and use:
url_report = request.get_full_path()
in the view, to get the current URL.
Else if you want to create a separate view for the reporting form. You can use
url_report = request.META.get('HTTP_REFERER')
to get the previous or refering URL which led the user to that page.
request.META.get('HTTP_REFERER') will return None if it come from a different website.

logout by deleting cookies

I used this code to logout from a django web app. but if I add url manually, it easily redirect me to that page,but that shouldn't happen since I'm logged out.
def logout_view(request):
user = check_validation(request)
response = HttpResponseRedirect('/login/') #redirect to login page
stoken = SessionToken(user=user) #stoken is object for SessionToken
response.delete_cookie(stoken.session_token)
return response`
Please tell me any solution to this problem,or anything that i am missing in this code.
Thanks in advance :)
In Django, there is a built in logout function. Use it, instead of baking your own:
from django.contrib.auth import logout
def logout_page(request):
logout(request)
return HttpResponseRedirect('/login/')
Hope it helps!

How to cancel navigation in a django view when an error occurs

I would like to do the following:
I am displaying view1, with template1. There is a link to view2, rendering template2
The user clicks the link
When processing view2, an error occurs
Now come the interesting part: I want to cancel rendering of view2, activate an error message, and display the previous view1/template1 (a kind of redirection, but not quite) But in view2 I do not know that I was coming from view1, and I also probably do not have the context that I had when view1 was rendered
How can I re-render view1, with the error message genarated in view2, so that the user the only new thing that sees is that error message? The full template1 should be rendered as before, including any form values that the user has entered.
This is similar to form validation, but would happen in the destination view instead of the form view.
Is this at all doable, or am I trying to do something completely impossible?
There doesn't seem to be a way to "abort" a view, but you can get the behavior you want with the following pattern:
from django.contrib import messages
from django.shortcuts import redirect
def view1(request):
if request.method == 'GET':
initial_data = request.session.get('post_data', {})
form = MyForm(initial=initial_data)
...
def view2(request):
...
if error:
request.session['post_data'] = request.POST
messages.add_message(request, messages.ERROR, "Oops!")
return redirect(request.META.get('HTTP_REFERER', '/'))
See this stack post for why preserving the POST data is painful and alternative ways of doing so.

Why will WTForms submit again when I refresh the page?

I created the following form:
class ContentForm(Form):
content = StringField(u'write here' , validators=[Required()])
submit = SubmitField(u'Let them know' )
When I submit, things seem to work. However, when I refresh the page afterwards, the form is submitted again. How do I fix this?
You need to redirect after making a POST request. Otherwise, the browser will do what you're experiencing (the behavior has nothing to do with WTForms).
#app.route('/my_form', methods=['GET', 'POST']
def my_form():
form = ContentForm()
if form.validate_on_submit():
# do stuff
return redirect('my_form') # or wherever
return render_template('my_form.html', form=form)

Django HttpResponseRedirect

I have created a basic contact form, and when the user submits information, it should redirect to the "Thank You" page.
views.py:
def contact(request):
# if no errors...
return HttpResponseRedirect('/thanks/')
urls.py:
(r'^contact/$', contact),
(r'^contact/thanks/$', contact_thanks),
Both pages work at the hard-coded URL. However, when I submit the form on /contact/ it redirects to /contact (no ending slash), which is a nonexistent page (either a 404 or an error page telling me I need a slash).
What is the reason it not correctly redirecting, and how can I fix this?
UPDATE: the return HttpResponseRedirect('/contact/thanks/') is what I now have, but the problem is that the submit button (using POST) does not redirect to the URL -- it doesn't redirect at all.
It's not the POST button that should redirect, but the view.
If not differently specified, the form (the HTML form tag) POSTs to the same URL. If the form is on /contact/, it POSTs on /contact/ (with or without slash, it's the same).
It's in the view that you should redirect to thanks. From the doc:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
Change /thanks/ to /contact/thanks/ and you're done.
All of the responses are correct but a better approach is to give names to your URLs in urls.py and hint to them in views with reverse function (instead of hard coding URL in views).
urls.py:
(r'^contact/$', contact, name='contact'),
(r'^contact/thanks/$', contact_thanks, name='thanks'),
And hint them in views.py like this:
from django.urls import reverse
return HttpResponseRedirect(reverse('app_name:thanks'))
This is better for future approach and follow the DRY principle of Django.
I believe that apart from Aviral Dasgupta's solution, OP also needs to change the relative url.
return HttpResponseRedirect('/thanks/')
to
return HttpResponseRedirect('/contact/thanks/')
/thanks/ should take the url to root: yoursite/thanks/ and not yoursite/contact/thanks/.
Just try this. It worked for me.
return HttpResponseRedirect('thanks/')
Note:- Remove the forward slash before
Use the Django APPEND_SLASH setting.
APPEND_SLASH
When set to True, if the request URL
does not match any of the patterns in
the URLconf and it doesn't end in a
slash, an HTTP redirect is issued to
the same URL with a slash appended.
Note that the redirect may cause any
data submitted in a POST request to be
lost.

Categories