Sending a POST request to python function via an HTML form - python

I am absolutely new to HTML and I was wondering if Someone could help me out. I tried looking for similar questions as mine but I didn't find anything quite like what I am looking for. Sorry if this question seems dumb or easy to you I am trying to learn! So basically I have an ID that I can access inside of my HTML file and I want to send it to my python function through a form, I have already managed to do this for buttons but never for a form. This is how I would send my ID to my function with a button:
<a href="{{url_for('validate_comment', item_id=msr.id)}}"> <--- the msr.id is my ID
<button type="button">
<div class="font-weight-bold">Ajouter un commentaire</div>
</button>
</a>
And this works perfectly but i was wondering if there was any way to do the same with a form as I am not calling a function but doing an action instead. This is how my form looks:
<form id="commentaire_form" method="post" action="/testement"> <--- here is where I give the route but how can i send the ID to the function linked to this route?
<textarea id='text' name="text"></textarea>
<input type="submit">
</form>
If anyone could help me I would greatly appreciate it, thanks in advance :-)

The below will make a POST request to the /testement route/URL. You can catch the id POST value in your python script.
<form id="commentaire_form" method="post" action="/testement">
<textarea id='text' name="text"></textarea>
<input type="hidden" name="id" value="{{ msr.id }}">
<input type="submit">
</form>

Related

bootstrap tags input tag value is not submitting with form

Can someone explain what is going on here? I don't understand why the values that I submit in the tag input field are not being submitted with the form. I've tried this with both examples
and neither will send the values correctly.
I am using bootstrap4-tagsinput
HTML CODE:
<form class="needs-validation" action="/archive" enctype="multipart/form-data" method="POST">
<div class="form-group">
<label>Solution Name</label>
<input name="solution_name" type="text" class="form-control" required>
<label>Vendor Name</label>
<input name="vendor_name" type="text" class="form-control" required>
</div>
<div class="form-group">
<label>Attachment</label>
<input name="file" type="file" class="form-control-file" required>
</div>
<div class="form-group">
<label>Tags</label>
<input class="form-select" name="tags" data-role="tagsinput">
</input>
</div>
<button type="submit" value="upload" class="btn btn-primary">Submit</button>
</form>
Server
#review_archive_host.route('/archive', methods=["GET", "POST"])
#login_required
def archives():
if "review_archive" not in session['u']['flags']:
flash("You do not have permissions to access that feature/page")
return redirect(get_redirect_url())
#archive search page
if request.method == "POST":
#create a new archive record
d = request.form.to_dict(flat=True) or {}
return d
Example form and response:
response:
{
"solution_name": "asdfs",
"tags": "",
"vendor_name": "asfsd"
}
In the documentation of the link you provided informs that this puglin was designed for Bootstrap 2.3.2 and 3. By the tag of your question, I saw that you are using 4.
And others people having issues using it on Bootstrap 4.
I uploaded a small example based on your form and method for Github, but using version 3 of Bootstrap and it worked as expected.
An alternative could be this. They fix the compatibility problem with bootstrap 4 based on the plugin you used initially
EDIT:
After your answer's update using Nodws/bootstrap4-tagsinput I made a small test using this plugin and I was able to reproduce the problem.
When analyzing the request.form sent, I noticed that with this version of the plugin the key tags are coming in duplicate.
ImmutableMultiDict([('vendor_name', u'vendor'), ('solution_name', u'solution'), ('tags', u''), ('tags', u'tag1,tag2')])
Because of that you dont get any value when your route parser the form to dict.
I replicate your code with this another version of plugin and now is working as expected.
The complete example continues on my Github.
The plugin in the documentation is for bootstrap 2.3.2 or 3 and would not work for bootstrap 4.
In order to use that plugin, you could downgrade your bootstrap to version 3.
An alternative would be the Bootstrap 4 Tag Input Plugin With jQuery - https://www.jqueryscript.net/form/Bootstrap-4-Tag-Input-Plugin-jQuery.html

How can I get the data-value of an HTML button in Flask?

<form action="/" method="post">
<button class="btn btn-outline-primary btn-sm" type="submit" name="submit_btn" value="favorites" data-
value="{{[i]}}">Favorites</button>
</form>
I have this button in Html, I want to obtain the variable "i" which is contained in the "data-value", to use it in Python, I'm using Flask also, thanks!.
The server (Flask/Python) won't have access to the data-value attribute when you submit the form. It's not part of the data that gets sent to the server.
You might try adding a "hidden" form element, which will send a key/value pair to the server without displaying anything to the user:
<form action="/" method="post">
<input type="hidden" name="value" value="{{[i]}}">
<button class="btn btn-outline-primary btn-sm" type="submit" name="submit_btn" value="favorites" data-value="{{[i]}}">Favorites</button>
</form>
As you can see, you can retain the data-value attribute on the button, but it's not doing anything so only keep it if you're using it in Javascript somehow.
Also note that {{[i]}} will output the string representation of an array with one value, i. So the value you will get on the server is "[5]" if i is 5 for instance. If you want an actual array on the server, there are other ways to do that.

Python Flask: Bad Request on Post method with radio-option checked

Lets say I have 2 radio buttons in my html script, of which one is checked by default:
<form action="" method="post">
<div class="radio-option checked">
<input type="radio" name="radioName" value="val_1"/>
</div>
<div class="radio-option">
<input type="radio" name="radioName" value="val_2"/>
</div>
<div>
<input type="submit" value="Confirm and continue"/>
</div>
</form>
If I click the submit button without clicking the other radio button, I get an error:
Bad Request The browser (or proxy) sent a request that this server
could not understand.
This happens because there is no value which is being transfered if a radio button is checked by default but not being selected with the mouse afterwards! This is what request.form shows me ImmutableMultiDict([]). If I select the other radio button with the mouse and click the submit button it shows me values ImmutableMultiDict(['radioName', 'val_2'])
I tried to catch the error like this, but it didn't work out:
if request.form == '':
flash('error')
return render_template('default_template.html')
How can I handle this within flask?
How can I set a default value, which can be sent to the server?
You could perform a check within flask. Check if request.form has items or if its empty and throw the error in that case.
A simple way of knowing if its empty would be, for example:
if len(request.form) == 0:
print('Error: The form is empty')
else:
print('The form has data, we can proceed')
Another way is:
if 'radioName' not in request.form:
print('Error: The form is empty')
...
But maybe flask has a better way of doing this or there are better practices to follow in these cases.
On the other hand, in the html snippet that you posted, none of the inputs is checked by default.
You have the checked css class on a div but not the checked attribute in an input with type=radio.
The correct use of checked attribute would be as follows:
<form action="" method="post">
<div class="radio-option checked">
<input type="radio" name="radioName" value="val_1" checked/>
</div>
<div class="radio-option">
<input type="radio" name="radioName" value="val_2"/>
</div>
<div>
<input type="submit" value="Confirm and continue"/>
</div>
</form>
This way, the radio input with value val_1, will be checked by default, populating the dictionary that goes to the server.
For more information, check out: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio
You can also avoid sending empty forms to the server using the required attribute to make sure that the user fills the form as expected.
To learn more about this: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation
I hope it helps!

can you change the way get method makes links for django?

I'm using django for a website that has a searchbar setup with a simple form:
<form method="get" action="/browse">
<div class="input-group col-md-12">
<input type="text" name="searchquery" class="form-control input-lg" placeholder="Search" style="margin-right:1vw; border-radius: 5px;"/>
<span class="input-group-btn">
<button class="btn btn-primary btn-lg" type="submit">
{% fontawesome_icon 'search' color='white' %}
</button>
</span>
</div>
</form>
This creates url's like this:
http://127.0.0.1:8000/browse/?searchquery=<searchquery>
However I've setup my django url like this:
http://127.0.0.1:8000/browse/<searchquery>/
I would like to use the second url (as it just looks a lot better in my opinion).
Is there a way I can make my form do this?
This isn't a question about Django. The browser simply can't do this with an HTML form. The action attribute of the form is set when it is loaded.
You could possibly write some JavaScript to make it do this. But that would be the wrong thing to do. Queries like search should be part of the querystring, not the URL.

Uploading Images Django Python

html:
<label for="image">Image</label>
Select a file: <input type="file" name="img">
Python:
image = (request.FILES.get("img"))
When I print image it prints none. If I just use {{form}} in between the <form> </form> tags it does send the image across to the view. However, for some specific reason I do not want to use the {{form}} method.
Any ideas how I can approach this problem? Thanks in advance!
Make sure your <form> has enctype="multipart/form-data", so it should look something like:
<form method="post" action="{URL}" enctype="multipart/form-data">
<input ...>
</form>

Categories