flask dynamic post url - python

I've built a nested drop down menus on my HTML and based on what user clicks inside nested dropdown, I want it to change the default value inside WTF form and post it to database.
So I have multiple different views pointing to one 'post' view. These multiple different views are different menus in my nested dropdown menus.
views
#app.route('/first_drop_down')
def first_drop_down():
return redirect('http://127.0.0.1:5000/post_something/first/')
#app.route('/second_drop_down')
def second_drop_down():
return redirect('http://127.0.0.1:5000/post_something/second/')
#app.route('/post_something/<some_parameter>', methods=['GET','POST'])
def post_something(some_parameter)
some_form = SomeForm()
if some_parameter == 'first':
some_form = SomeForm(field_a = some_parameter)
elif some_parameter == 'second':
some_form = SomeForm(field_a = some_parameter )
if some_form.validate_on_submit():
.
.
.
.
insert to db
return redirect(url_for('index'))
return render_template('user_input.html', some_paramter = some_paramter)
So the problem that I'm having is that I keep getting 404 right after I press submit on my form. And when doing get request on post_something view, the url is /post_something/first/ but after pressing the submit button the url changes to /post_something// , so the url is empty for post and I'm guessing thats why it is throwing 404.
Even though I kind of assume why this is happening, I am kind of stuck of what to do to maintain that url when posting. Any help will be appreciated.

from the flask api documentation, you will notice
1. If a rule ends with a slash and is requested without a slash by the user, the user is automatically redirected to the same page with a trailing slash attached.
2. If a rule does not end with a trailing slash and the user requests the page with a trailing slash, a 404 not found is raised.
Now that you have defined:
#app.route('/post_something/<some_parameter>', methods=['GET','POST'])
you should use /post_something/first in your form; Or use url_for('post_something') instead.

Related

get request data from Flask redirect

I have to create a small web app in Flask which contains an API and also an interface and I'm facing the following problem:
This would be how i handle a GET request:
#app.route('/member/<id>', methods=['GET'])
def member_get(id):
member = cursor.execute(f"select * from members where id={id}").fetchone()
if member is not None:
return to_json(member), 200
else:
return 'Not found', 404
And I would like to create some small forms with which I could do GET,POST,PUT,DELETE operations.
This would be how I get the data from the form:
#app.route('/dashboard', methods=['POST'])
def dashboard_post():
id = request.form['get_id']
return redirect(url_for("member_get",id=id))
My question is how can I get the data from the API method without actually redirecting to that page?
More precise, can I call somehow redirect(url_for("member_get",id=id)) and get the response data directly? (if I print the return of the redirect method it only shows the request status)
I assume one solution would be using the requests module, but is there a way to do it directly in Flask?
First of all, an API should always return a response in a format that is consistent and predictable. The code for member_get returns JSON in case of success but plain text in case of failure. This is not okay. You should return JSON always, with the appropriate HTTP status code. Here you are using 404 to express Not found, this is good.
You can use the jsonify function in Flask for that. And maybe normalize the response, so that is always has the same shape, whether the member ID is found or not.
Otherwise, parsing the response from your API will be harder because it is not consistent depending on the scenario.
Second point, if I understand it right: if you want to invoke the route '/member/' from within your API, you could simply do:
return member_get(id)
You call the function that is attached to the route, not the route itself. Of course you could actually fetch the page with the requests module but this is unnecessary, since the function is available internally.
Your question is not clear, but as I understand, (1) you think you have to get your form data from one view and send it to another view to do operations. (2) you are not familiar with flask request and flask-wtf. and maybe (3) looking for a way to do this without refreshing or redirecting the page.
You don't need to separate your GET and POST methods. instead you can integrate both in one view.
#app.route('/member/<id>', methods=['GET', 'POST])
To handling data, you can use flask request.
from flask import request
and access to data in your view like this:
id = request.form.get("idField")
but you can also use Flask-WTF to simply make and handle forms.
with Flask-WTF your view would be like this:
from app.forms import SearchForm
#app.route('/your-endpoint', methods=['GET', 'POST'])
def yourView():
form = your_form()
if form.validate_on_submit():
id=form.idField.data
return render_template('test.html', form=form)
the condition form.validate_on_submit() checks if you are submitting a from or you just opened it. if you submit a form and it's data are valid based on validators defined in your form, the code runs. else just renders the template and returns the page.
To learn how to make forms with Flask-WTF I recommend reading this article:
If you don't want to refresh the page or redirect it after submitting the form, you can use AJAx on your page.

render_to_response or redirect changes the template elements in Django 1.8

I'm trying to check if email id entered by user is existing in the database table, if existing - I would like to route to 'prof.html' template otherwise just show a message in the login.html template.
Both the conditions are working fine.
However, the problem is when I use redirect() or render_to_response() -
the destination template elements like div, input etc., are being changed automatically (prof.html in this case) ?
Can we also send the context information to destination template ?
(response data or any object from the database and redirect to prof.html template via view in this case)
Below is my code :
Views.py
def verifyme(request):
if request.method == "POST":
emailid4loginV = request.POST['emailid4login_Aj']
else:
emailid4loginV = ''
response_data = ''
return HttpResponse(response_data, content_type="text/plain")
response_data = ''
if Employee.objects.filter(email = emailid4loginV).exists():
response_data='Thanks for waiting - login successful'
#return render_to_response('app/prof.html', { 'response_data':response_data},
# context_instance = RequestContext( request ) )
return redirect('/myprofile')
else:
response_data='Ouch! you are not a registered user!'
return HttpResponse(response_data, content_type="text/plain")
urls.py
url(r'^myprofile$', 'app.views.profile', name='profile'),
Just for your info, 'profile' view does return some objects from the table and renders in the template app/prof.html.
I observed that the destination template is being rendered in same login.html template (How ? : In the browser url, I dont see myprofile - but the one for login) But when I request the myprofile manually by entering in the website url (localhost:xxxxx/myprofile), it works perfectly :(
URL before submitting request in login.html :
URL after submitting request in login.html - myprofile is rendered in the same page :
When I manually type in the url, template just works perfectly..
Could you please let me know what could be the problem ?
EDIT:
Solved this issue with a little trick, posted in the below
https://stackoverflow.com/questions/31091938/why-is-httpresponseredirectreverse-doesnt-redirect-to-new-page
1) Actually there are many ways to pass data to next view ... generally in such cases like you have better way - using sessions (cookie|localstorage|sessionstorage), it is like clipboard ... save session data in one view and get it later in another one. For example:
First view:
self.request.session['response_data'] = 'some text'
self.request.session.set_expiry(0) # user’s session cookie will expire when the user’s Web browser is closed.
Other views:
response_data = self.request.session.get('response_data', '')
But if you planning just use this data in template Django has some kind more high-level interface for it and in your case semantically right to use it - The messages framework https://docs.djangoproject.com/en/1.8/ref/contrib/messages/
2) If you want redirect to another view better use url namespaces and reverse https://docs.djangoproject.com/en/1.8/ref/urlresolvers/#reverse
return HttpResponseRedirect(reverse(app.views.profile)) # here I've passed callable object because you have not show your app url namespace, but generally use namespaces
https://docs.djangoproject.com/en/1.8/topics/http/urls/#url-namespaces

passing GET parameter from python view to template

As simple as this is, I'm having trouble getting the value of a GET parameter d
I'm clicking on a link like:
http://127.0.0.1:8000/Account/Site/d=mysite.com
The view that, that url serves is:
#login_required
def Site(request):
if request.user.is_authenticated():
# verify domain in url is associated with authenticated users account
DomainToScan = request.GET.get('d')
VerifyDomainAgainstDb = Tld.objects.filter(FKtoClient=request.user,domainNm=DomainToScan)
else:
HttpResponseRedirect("/Login/")
return render(request, 'VA/account/begin_site.html', {
'Site':Site,
'VerifyDomainAgainstDb':VerifyDomainAgainstDb
})
specifically, this line:
DomainToScan = request.GET.get('d')
the value of DomainToScan is outputting as None when viewing the django template begin_site.html
What am I doing wrong here?
Thank you!
UPDATE:
urls.py
(r'^Account/Site/[?]d=[A-za-z0-9]{2,50}.[a-z]{1,3}$', Site),
For some reason this isn't matching a url like:
http://127.0.0.1:8000/Account/Site/?d=mysite.com
Any reason why? Rubular says its valid
You don't have any GET parameters. If you want domain to be a GET parameter, your link should be http://127.0.0.1:8000/Account/Site/?d=mysite.com - notice the ?.
(Also note you would need to actually return HttpResponseRedirect(), not just call it: but the whole checking of is_authenticated is pointless anyway because the function is decorated with login_required, so a non-authenticated user wouldn't even get into that view.)
Try:
#login_required
def Site(request, DomainToScan=None):
if request.user.is_authenticated():
# verify domain in url is associated with authenticated users account
VerifyDomainAgainstDb = Tld.objects.filter(FKtoClient=request.user,domainNm=DomainToScan)
else:
return HttpResponseRedirect("/Login/")
return render(request, 'VA/account/begin_site.html', locals())
urls.py
(r'^Account/Site/(?P<DomainToScan>[^/]+)/', Site),

How To Show Different Forms in a Web App Depending on a GET Parameter?

In a link in a web page I want to pass a GET parameter to a GAE web app in Python. So, if someone access the web app through this link, one form with some input fields will show up. If someone access the web app, i.e. by typing the web app url, another form with more input fields will show up.
Does someone know the best way to do this?
I tried the following but it didn't work:
def get(self):
q=self.request.get("q")
if q is None:
#show form with all fields
else:
#show form without all fields
def post(self):
#here I care about the added fields only if nothing was passed as a GET parameter
By default, get() returns the empty string ('') if the requested argument is not in the request (see documentation).
So for checking if an argument is missing, use
if q == '':
or
if len(q) == 0:

django forms - reusing form request functions

I have a base.html which most of my pages inherit. Inside it defines a header which contains a search box. The code for the search box is some thing along the lines of....
if request.method == 'POST':
if 'search_button' in request.POST:
location = request.POST['location']
# Do something with location here and redirect to another page...
return HttpResponseRedirect('/lostandfound')
I have a couple of questions. First of all, how do I ensure that this code is sat in all my other views without rewriting it every time, this wouldn't be very DRY!!
Also how do I redirect to another page and pass the variable 'location' along with it? HttpResponseRedirect isn't the right way to do it i'm sure!
You should POST your search form to it's own search view, and display the results on that page.

Categories

Resources