Variable URLs and passing non-input value from html to Python (Flask) - python

According to this question you can only send data from input forms from html to Python with POST. I'm trying to figure out how to pass a value (that's actually originally contained in a dictionary that I passed in from Python) from html to Python.
My two approaches I considered (and have not figured out how to do successfully) are:
Taking a look at the Flask quickstart, this should be quite simple. I'm just not sure what the syntax should look like on the html side to pass in this parkCode.
#app.route('/park/<parkCode>', methods =['GET', 'POST'])
def park(parkCode):
return render_template('park.html', parkCode = parkCode)
Alternatively, is there some way to simply send a string from html to Python without using an input form? I have yet to find a way to do this.
For reference, this is the line where I'm sending over the ```parks`` dictionary:
return render_template('search_results.html', parks=parks)
Then, in my search_results.html file:
{% for park in parks %}
<div method = "POST" action = "/park">{{park["fullName"]}}</div>
{% endfor %}
But I want the to send the park["fullName"] to my Python code.

.route decorator always handles only URL paths. Since form action is a static value in HTML, the only way to change it is to use JavaScript (for example, by changing the action attribute at submit time). If you're going to use JavaScript, you might as well then just use JavaScript to submit the request itself, which leads us to
Yes, you can use AJAX to send a request. Since ES6, the easiest way to do this is fetch. The choice of whether to use a form or whether to use AJAX depends on what you want to happen after the request: a submitted form results in a new page being rendered, while an AJAX request cannot change the current page, only trigger JavaScript code (although obviously you can change the page in JavaScript should you so wish).
Basically, you can't do what you want without JavaScript. The third option that does work without JavaScript is using the form as it was meant to be used. On flask side, it involves not naming the parameter inside the route, but using request.args (for GET forms) or request.form (for POST forms):
#app.route('/park', methods =['POST'])
def park():
parkCode = request.form.get('parkCode')
return render_template('park.html', parkCode = parkCode)
with the accompanying HTML:
<form action="/park" method="POST">
<input name="parkCode"/>
<input type="submit" value="Submit"/>
</form>

Related

keeping values after redirecting in google app engine python

I have just started learning web development using GAE and I have the following question. Isn't there any way to post data to the webpage after redirecting. I want input values to be kept after redirecting.
One way that you can do this is by including the information in your html template
<form action="" method="post">
<input type="hidden" name="passedValue" value = {{value}}>
</form>
Put the value that you want to be passed in {{value}} (add more inputs if necessary). So when you redirect, each page will store the value of the previous page, but you will need to add code to your main.py to sub the values into the html template through jinja as well.
Another way that I could suggest would be just storing the information in Datastore and then retrieving it at the final destination

Personalized/random URLs in Python/Django

I'm a Python beginner (and English language beginner too, by the way).
I just created a simple form in Python/Django that creates, edit and remove items.
I have HTML links that refers to my URLs like:
FILE.HTML:
<INPUT Type="BUTTON" VALUE="Edit" ONCLICK="window.location.href='/edit/{{ object.id }}/'">
URLS.PY:
url(r'^edit/(?P<id>\d+)/$', 'app.views.editobj'),
VIEWS.PY:
def editobj(request, id):
But of course, there's a problem, I wouldn't like people go direct on URL (only if the button was clicked) because somebody could just type on URL: /removeobj/1 and remove the object ID=1. What I would like to do is create differente URLs, maybe random, so the user would never guess what is the URL that the button will open, and of course, that it does work with the ID argument, so when it's goind to edit/remove, opens the right object.
I'm Hoping I was clear on my needs. Thanks.
Generating random URL's would be highly inefficient, not to mention unnecessarily difficult to implement. The common way to do what you are asking is to POST to a URL. I think you should do a little more reading on Django POSTing, as it will help you get a better understanding of what it does. In any case, here is an example of using this:
urls.py
url(r'^delete/$', 'app.views.delete_object', name="delete_obj"),
views.py
def delete_object(request):
""" Get the ID of an object via POST, then delete it. """
if request.method == 'POST' # This makes sure the request is a POST
obj_id = request.POST['obj_id']
obj = MODELNAME.objects.get(id=obj_id) # Use your model name here
# You can use if conditions here to make sure the object you just
# retrieved is allowed to be deleted by this user, or in general.
obj.delete()
messages.success(request, 'Object successfully deleted!')
return redirect(reverse('index')) # Make sure you use a name that exists
.html
<form method="POST" action="{% url 'delete_obj' %}">
{% CSRF_TOKEN %}
<input type="hidden" value="{{ obj.id }}" name="obj_id" />
<button type="submit">Submit</submit>
</form>
You can use more logic in the views.py to make sure that the object is allowed to be deletable, but for the most part, the code I wrote should give you somewhat of an understanding of the way to create a POST -> Delete Object workflow. Feel free to ask questions in the comment section below my answer.
The simplest way I see to do a "random" url would be to add a UUIDField (https://docs.djangoproject.com/en/1.8/ref/models/fields/#uuidfield or https://github.com/dcramer/django-uuidfield for Django <1.8) with a default to your model.
Your url can then become
url(r'^delete/(?P<uuid>[\da-f-]+)', 'app.views.delete_object', name='delete_obj')
uuid's are virtually impossible to guess.
Now if you don't add extra security to check that the user has the right to delete the object, anyone could still run a robot that would go through every single possible uuid and flush your database.
And if it is just a matter of not "guessing" #Hybrid's solution is probably a better starting point.

How to use <select> information in django form

So I have my django project which includes a HTML page that shows a list and a submit button.
I want to use the submit button to send the selected item ID to the server and than use it.
That`s my code :
<form>
<select>
{% for item in list %}
<option value={{item.name}}>{{ item.name }}</option>
{% endfor %}
</select>
<input type="submit"/>
</form>
The things I want to know are :
What to write in the action of the form so it will only reload the page.
How to enter the form data into a view.
As i understand, you want to take the value on your select and do something with it in the server.
I would advise you to read the documentation, as it is pretty detailed about what you need to know to work with forms. You should also read a little about forms, as you are missing a couple details.
Now, the action must point to one of your urls. Your url must be pointing to a view and in your view, if everything is ok, you should be getting a request object.
Depending on your post method, you have a python dictionary in request.GET or request.POST, filled with the values in your form.
That is assuming you are using your form created from scratch. In django you can use the Form class, which creates the html (or lets you create it, but giving you some constraints), validates the form, saves the form to a model (in the case it is a ModelForm). It is a valuable class for me and prefer it over working with raw html.
Also, assuming you haven't, i strongly advice you to go through the getting started. Even if it keeps things basic, it does a good job at introducing core django modules.

Remove URL Params after page loads in Google App Engine

First of all, I am very new to web programming in general. I've read lots of tutorials online and it's a little confusing since some of them are out-dated. So if I'm heading down a path that is fundamentally wrong, I'd love suggestions about The Right Way. Having said that, this is just a for-fun project, so if there is a simple (<10 lines) way to get what I want, I'd love to see quick results today even if long-term I end up fundamentally changing things.
So anyway, I'm using Google App Engine (Python 2.7) to do a simple calculation. I show a form, the user fills in values, clicks a button at the bottom, and some result text is displayed with the result of the calculation. This part is working fine.
For my own testing, it's annoying to always re-type the input values, and some of the fields aren't totally obvious to users, so I'd like to be able to send a link to someone off the form "http://buggyapp.appspot.com/calculation?input1=100&input2=200" and have it fill in those two parameters. This part works, too.
The problem is when the user loads that sort of link, changes one of the values in the form, and then clicks the button. Instead of using the (changed) form value, it uses the value in the URL. I'd like to fix that, and ideally I'd like the URL bar to not even show the URL Params after the page loads.
I'm not sure what info is necessary to help you find what I'm doing wrong.
Here's a section from the HTML, which is a Jinja2 template:
<form method="post">
<input value="{{ input1 }}" name="input1">
<input value="{{ input2 }}" name="input2">
<button class="submit" type="submit">Calculate</button>
</form>
<p>{{ result }}</p>
Here's the python code:
def get(self):
input1 = request.get('input1')
input2 = request.get('input2')
# some irrelevant(?) code to set default values on the initial load if there are no URL Params
result = str(input1+input2) #actual calculation slightly more complicated than this
template = JINJA_ENVIRONMENT.get_template('calculation.html')
self.response.write(template.render(vars()))
It seems to behave the same no matter whether I put the calculation in the get handler or post handler. At the moment, I'm simply calling one from the other:
def post(self):
input1 = request.get('input1')
print input1 # even this shows the URL value (if one exists), not form value
return self.get();
So, my next step to make it work would be to change the names of the form inputs so they are different from the URL Params, and add extra code to merge the potential input sources. But that won't really get me what I want, which is for the URL Params to disappear once they have populated the input forms. It also complicates the part of the code that generates those sorts of links.
I'd prefer a Python-only solution, but I'm open to using javascript. There are other stack overflow questions/answers that imply a javascript mechanism will do what I want, but I don't understand any of them well enough to apply them to my problem.
I'm sure I'm doing lots of other things wrong, and I may have over-simplified things or not posted enough info. I'm here to learn, so fire away. And thanks in advance for the help.
tl;dr- How do I use the URL Params once and then remove them from the URL so they don't override form inputs on subsequent posts?
HTTP GET requests usually include the parameters in the URL since there's no other place to pass them (there's no request body).
HTTP POST requests usually include the parameters in the request body, though it's still possible to include the parameters in the URL.
It looks like you're using some sort of Javascript to post the form. Make sure you are using a POST request and putting the parameters in the POST body. Most libraries automatically put params in the POST body as long as you're issuing a POST request.
EDIT:
Forms usually issue POST requests by default. Usually the <form> element will have an action attribute that specifies the URL to send to. However, if it doesn't have an action attribute it'll issue a POST request to the current URL.
In your case the current URL contains parameters and those are submitted again with your request. You should have a few options.
Specify the action in your form so you aren't submitting to the same url with parameters already attached.
In your request handler, read the data out of the post body (request.POST['input1']) instead of the url.

Rendering JSON objects using a Django template after an Ajax call

I've been trying to understand what's the optimal way to do Ajax in Django. By reading stuff here and there I gathered that the common process is:
formulate your Ajax call using some JavaScript library (e.g., jQuery), set up a URL pattern in Django that catches the call and passes it to a view function
in the Python view function retrieve the objects you are interested in and send them back to the client in JSON format or similar (by using the built in serializer module, or simplejson)
define a callback function in JavaScript that receives the JSON data and parses them, so to create whatever HTML is needed to be displayed. Finally, the JavaScript script puts the HTML wherever it should stay.
Now, what I still don't get is how are Django templates related to all of this? Apparently, we're not making use of the power of templates at all.
Ideally, I thought it'd be nice to pass back a JSON object and a template name, so that the data could be iterated over and an HTML block is created. But maybe I'm totally wrong here...
The only resource I found that goes in this direction is this snippet (769) but I haven't tried it yet.
Obviously, what's going to happen in this case is that all the resulting HTML is created on the server side, then passed to the client. The JavaScript-callback function only has to display it in the right place.
Does this cause performance problems? If not, even without using the snippet above, why not formatting the HTML directly in the backend using Python instead of the front-end?
Many thanks!
UPDATE: please use snippet 942 because it is an enhanced version of the one above! I found that the inheritance support works much better this way..
Hey thanks vikingosegundo!
I like using decorators too :-).
But in the meanwhile I've been following the approach suggested by the snippet I was mentioning above. Only thing, use instead the snippet n. 942 cause it's an improved version of the original one. Here's how it works:
Imagine you have a template (e.g., 'subtemplate.html') of whatever size that contains a useful block you can reuse:
........
<div id="results">
{% block results %}
{% for el in items %}
<li>{{el|capfirst}}</li>
{% endfor %}
{% endblock %}
</div><br />
........
By importing in your view file the snippet above you can easily reference to any block in your templates. A cool feature is that the inheritance relations among templates are taken into consideration, so if you reference to a block that includes another block and so on, everything should work just fine. So, the ajax-view looks like this:
from django.template import loader
# downloaded from djangosnippets.com[942]
from my_project.snippets.template import render_block_to_string
def ajax_view(request):
# some random context
context = Context({'items': range(100)})
# passing the template_name + block_name + context
return_str = render_block_to_string('standard/subtemplate.html', 'results', context)
return HttpResponse(return_str)
Here is how I use the same template for traditional rendering and Ajax-response rendering.
Template:
<div id="sortable">
{% include "admin/app/model/subtemplate.html" %}
</div>
Included template (aka: subtemplate):
<div id="results_listing">
{% if results %}
{% for c in results %}
.....
{% endfor %}
{% else %}
The Ajax-view:
#login_required
#render_to('admin/app/model/subtemplate.html')#annoying-decorator
def ajax_view(request):
.....
return {
"results":Model.objects.all(),
}
Of course you can use render_to_response. But I like those annoying decorators :D
There's no reason you can't return a rendered bit of HTML using Ajax, and insert that into the existing page at the point you want. Obviously you can use Django's templates to render this HTML, if you want.
When you are doing Ajax I don't think you have any use for templates.
Template is there so that you can generate dynamic HTML on the server side easily and hence it provides few programming hooks inside HTML.
In case of Ajax you are passing JSON data and you can format it as you want in Python.
and HTML/document elements will be generated on client side using the JSON by some JavaScript library e.g. jQuery on client side.
Maybe if you have a very specific case of replacing some inner HTML from server side HTML then maybe you can use templates but in that case why you would need JSON?
You can just query the HTML page via Ajax and change inner or outer or whatever HTML.
Templates are for the purpose of presentation. Responding with data in format X (JSON, JSONP, XML, YAML, *ml, etc.) is not presentation, so you don't need templates. Just serialize your data into format X and return it in an HttpResponse.
While templates are indeed just for presentation purposes, it shouldn't matter if you are doing it on the serverside or client side. It all comes down to separating the control logic that is performing an action, from the view logic that is just responsible for creating the markup. If your javascript control logic is having to handle how you are rendering or displaying the HTML, then you might be doing it wrong, but if you isolate that rendering logic to another object or function, and just passing it the data necessary for the render, then you should be fine; it mirrors how we separate our controllers, models and views on the server side.
Take a look at the github project: http://github.com/comolongo/Yz-Javascript-Django-Template-Compiler
It compiles django templates into optimized javascript functions that will generate your presentation html with data that you pass it. The compiled functions are in pure javascript, so there are no dependencies on other libraries. Since the templates are compiled instead of being parsed at runtime, the strings and variables are all already placed into javascript strings that just need to be concatenated, so you get a huge speed increase compared to techniques that require you to do dom manipulation or script parsing to get the final presentation. Right now only the basic tags and filters are there, but should be enough for most things, and more tags will be added as people start making requests for them or start contributing to the project.
You can use jquery.load() or similar, generating the HTML on the server and loading it into the DOM with JavaScript. I think someone has called this AJAH.
Unfortunately, Django templates are designed to be executed server side only. There is at least one project to render Django templates using Javascript, but I haven't used it and so I don't know how fast, well supported or up to date it is. Other than this, you have to either use the Django templates on the server or generate dynamic elements on the client without using templates.

Categories