Tom Kealy Tom Kealy - 1 year ago 44
HTML Question

Saving the content of a <textarea> to file with Bottle

I'm writing a small web portal which will enable users to annotate some text, for a computational linguistics project, and save their annotations to file.

I'm having trouble getting the modified text to be saved.

My page is:

from bottle import template
from project import app
from bottle import request
from bottle import redirect
import random

def index():
notices = 'This is a placeholder text for StackOverflow'
return template('annotator/index', package=notices)

@app.route('/annotator/submit', method=['GET'])
def submit():
with open('output.txt', 'w') as outfile:
package = str(request.GET.get('package'))

The layout of my page is:

<!doctype html>
<link rel="stylesheet" type="text/css" href="/css/style.css">
<title>My App</title>
<div class="page">
<h1>NM Annotator Demo V 0.1</h1>
% if package is not '':
<form action='annotator/submit', method="GET">
<textarea name="package" ROWS=20 COLS=70>{{package}}</textarea>
<td><INPUT TYPE=SUBMIT name="package" VALUE="Submit"></td>

And the submit page is:

<form action="annotator/submit" method="post">
Thank you
%rebase layout/layout

However, only the word 'submit' is being saved in the file - not the content of the - which is what I want to get saved, as it will be the result of the annotation.

This is my first web app, and I'm a bit confused.

Answer Source

Your textarea and your submit form items are both named "package".

Change your button to this and see if that helps:

<INPUT TYPE=SUBMIT name="submit" VALUE="Submit">

EDIT: Explanation

The problem with having two form items that have the same name is that your application receives them both, on the query string. For example,

In your app, you'll effectively get a dict of the query args, and it will either look like {'package': 'sometext'} or {'package': 'Submit'}. Which one you get depends entirely upon the application (Bottle), but the most likely implementation--to process the query args in order--would result in the second value taking precedence, as it overwrites the first.

Most web frameworks expose a way to get all query args for a given name; in Bottle, it's request.query.getall. So request.query.getall('package') would return ['sometext', 'Submit']. But in your case it makes much more sense to avoid the name collision in the first place, rather than keep it and then retrieve multiple values.

Hope that helps!