A simple question about POST and GET request - python

I just started to learn Django by following a sentdex tutorial. During the course, we added a User model into our database and we created a function in our views.py file:
def register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():#si les champs sont OK :
user = form.save()
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages:
print(form.error_messages[msg])
But in this piece of code, I don't understand how Django knows if the request.method is True or False. Is it because I created a form with a Submit button in my template ?

Its impossible to say exactly what happens in your case since we don't have your HTML but in general:
When you create an HTML form, you can specify a method as follows <form method="POST"></form> or <form method="GET"></form>. If you don't specify the default is GET.
When you submit your form, it sends the data using an http request of the specified type. This is what Django is reading.

In this case, request.method simply represents the HTTP method that was used to access your view. For example, your register function might be assigned a url configuration such as: url(r'^register/', views.register), which maps an incoming HTTP request to your view. If you have a web form with a 'Submit' button, it's likely the web application code is submitting an HTTP POST request to your web server.
Django automatically constructs the request object for you, so you can check in your view how the request was made against the web server. For more info about what other things are included in the request, check the Django docs.

Related

Flask WTForms - Retrieve form data when submitting to a different route, i.e. a different POST route than the GET route which renders the form

I would like to set up my URLs/endpoints according to REST as closely as possible, while still utilising Flask-WTForms.
I would like my form to render at GET /posts/new, and submit to POST /post.
With Flask-WTForms I can only work out how to get it to GET/POST to the same URL.
My current code looks like this:
#post_bp.route('/posts/new', methods=['GET', 'POST'])
def show_post_form():
create_post_form = CreatePostForm()
if create_post_form.validate_on_submit():
return 'success'
return render_template('create_post_form.html', form=create_post_form)
However I would like to be able to make it look something more like this, but I just can't seem to work it out:
#post_bp.route('/posts/new', methods=['GET'])
def show_post_form():
create_post_form = CreatePostForm()
return render_template('create_post_form.html', form=create_post_form)
this route only shows the form
the form submits a POST request to /post
<form action="{{url_for('shipment.C_shipment')}}" method="POST" novalidate>
the POST /post route handles the submitted form and if there are errors for example, then it redirects back to GET /posts/new:
#post_bp.route('/post', methods=['POST'])
def create_post():
create_post_form = CreatePostForm()
if create_post_form.validate_on_submit():
return "success!"
if len(create_post_form.errors) != 0:
for error in create_shipment_form.errors:
for msg in create_shipment_form.errors[error]:
flash(msg)
return redirect(url_for('shipment.show_create_shipment_form'))
i guess creating a new CreatePostForm() object here doesn't really work..
Any suggestions?
Creating a new CreatePostForm is correct as it parses the submitted form data for you. This allows you to call validate_on_submit() on the form object.
I don't think you're generating the correct URL for the form action in your HTML snippet. The argument to url_for() should be the desired endpoint (see docs) which should be <post_bp>.create_post. This would be similar to your call
return redirect(url_for('shipment.show_create_shipment_form'))
If this does not fix the issue, please provide both frontend and backend error messages you receive when trying to send the data to /post.

Twilio django send SMS and get answer using SMS as parameter

In the twilio example made in flask, I can send an SMS and receive an answer using text and the SMS as the search parameter in the database. I need make this but in a django project, my first option that I thought make a django view with a parameter using a url with for send the parameter, but I see that is bad idea because not is possible can use the text of SMS as parameter
This is a part of flask example
#app.route('/directory/search', methods=['POST'])
def search():
query = request.form['Body']
I need make some similar to that view in django using django restframework but how I can get the Body (I think that the body is the text send in the SMS)
for use this as parameter
Use request.POST to access the form data:
from django.shortcuts import render
def my_view(request):
if request.method == "POST":
data = request.POST
# all posted data
data['body']
# the rest of your view logic
return render(request, 'template.html', context)

Django froms submit action and HttpResponseRedirect difference

Referring from the form topic of django documentation, if in a view function I write,
if form.is_valid():
return HttpResponseRedirect('/thanks/')
And in the form template I give the action like,
<form action="/your-name/" method="post">
Then on submit the form will go to the view mapped tho /your-name/ url in urls.py but what about the HttpResponseRedirect('/thanks/') line in the function from where I rendering the form? If a form is valid then I save the form. but what will be the url in the action of the form. now def get_name(request): is the function mapped to /user/ url. I hope you understand my confusion here. need some help.
This is an exemple of the "post redirect get" pattern - if a post is succesfull (the form was valid and the processing went ok), it's good practice to return a redirect, which will be followed by a get from the user-agent on the url you redirected to. It avoids multiple submissions if the user try to reload the page.
Where you redirect to is up to you - you can just redirect to the same view (usually displaying a success message to the user), or redirect to another view.
As a side note: hardcoding urls is a bad practice in Django, you should use the url reverse feature instead.

Django- why inbuilt auth login function not passing info about user to after successful login url

Hi I used the django inbult auth urls and views for my project and now have finished the initial user account creation/login/reset password process.
Now, the user can log in and be redirected to the after successful login url accounts/profile/.
I have several doubts on the django login function. For convenience, I've copy paste the django inbuilt login function code below.
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(request, data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
My questions are:
1 Is the REDIRECT_FIELD_NAME in the function set as '/profile/' in django.contrib.auth ?
I could see this variable is imported from django.contrib.auth
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout, get_user_model
I don't have any setting for this variable, but after user successfully logged in, the page will be directed to /accounts/profile/
2 Has the login function passed the account info about the user? If yes, how can I access it?
From the code, if user successfully logged in, page will be redirected: return HttpResponseRedirect(redirect_to)
in my case, redirected to accounts/profile/ , initially the view for the url was simply a
HttpResponse("You have logged in successfully")
now when I am trying to implement the view function, I realize that no info about the user has been passed.
I've tried to print request in the view function, but there is no info about the user in the message printed in the server terminal, all I get is a long list of system settings or other info. However, the login should pass the info of who has just successfully logged in to the successful log in urls right?
Thank you very much for explaining.
After the login, you can access the user info by referring request.user in views and just {{user}} in templates. All you need to make sure is you're passing the RequestContext in the HttpResponse for the future request.
Yes, REDIRECT_FIELD_NAME is defined in __init__.py of django.contrib.auth which is simply a "next" what you passed from the login form.
In Django, there are more than one ways to force a user to login. By decorating a view function with #login_required, by calling the build-in login view for an user defined URL and etc., Refer about the login settings variables here. You'll get some more ideas.
Building custom login page. That link gives you an example for custom login implementaion. Consider you have decorated a view with #login_required and it's corresponding URL is /login_test/. Then the {{next}} context variable in the login form will be rendered with /login_test/. So after you login,
<input type="hidden" name="next" value="{{ next }}" />
This element's value will be taken for redirecting as per the REDIRECT_FIELD_NAME. Though I suspect that that example is missing the setting of settings.LOGIN_URL to the URL login/. Never mind, it's being passed as an argument in the decorator itself.
To override this behavior just put following in settings.py of your app :
LOGIN_REDIRECT_URL = "/"
This will redirect to your home page. You can change this url to preferred url.
Once the user is redirected to accounts/profile/ the view for that link will be returned. You can access information about the currently logged in user there as per this post by using request.user. Also tip to see what information you have access to in your views. Use import pbd; pdb.set_trace(). This pops you into a python prompt with access to all of the current variables. To see all the defined variables call locals(), though this will print out a ton of junk along with it. In the template you can display a "you can't access this page" message if the user isn't logged in.

Clear POST in web page

I have a small python/django web site and I'm using a html form POST some information, annoyingly however this information is stored in POST so when a user refreshes in say IE/chrome they get that warning message about the page containing POST data. How do I clear the POST data after it has been processed so a user can refresh and not see this warning message?
Also I have some logic as follows that detects a POST
if request.method == "POST":
do something
Select all
Open in new window
This is fine when I actually post the form, but when I refresh the page it also detects the POST and does the logic that I now dont want to do.
How can I solve this also??
Thanks
After form is validated and it is valid. Then do the redirect to some other page e.g. a success page or redirect to the same view. The redirection will avoid Double Form Submition problem. Read more about it here.
Use HttpResponseRedirect when you return the response for POST request. This is explained in tutorial 4 as
After incrementing the choice count, the code returns an HttpResponseRedirect rather than a normal HttpResponse. HttpResponseRedirect takes a single argument: the URL to which the user will be redirected (see the following point for how we construct the URL in this case).
As the Python comment above points out, you should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn't specific to Django; it's just good Web development practice.
As Rohan said, you should use HttpResponseRedirect. But also you can use a shortcut:
from django.shortcuts import redirect
def some_view(request):
if request.method == 'POST':
# do smth
return redirect('/page-with-form/')

Categories