Search code examples
pythonhtmlbottle

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


@app.route('/')
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'))
        outfile.write(str(package))
        redirect('/')

The layout of my page is:

<!doctype html>
 <head>
     <link rel="stylesheet" type="text/css" href="/css/style.css">
     <title>My App</title>
 </head>
 <body>
     <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>
     </form>
         %end
         %include
    </div>
</body>

And the submit page is:

<form action="annotator/submit" method="post">
<dl>
Thank you
</dl>
</form>
%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.


Solution

  • 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,

    http://yourserver.com/annotator/submit?package=sometext&package=Submit

    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!