Interactive Form Example
Here is an example interactive form application. The interface UI is driven by the built-in webserver. It's based on some of the code in Ole's file transfer script. However, in this case, the pages are served directly to the web browser component inside Pythonista. You do not need to view it from another computer--although, if you know the device's address you can do that too.
I am a newbie to Python and GitHub, so my apologies if there are style or formatting errors. I have tested this on my iPhone and two iPads (it was written on a mini) as well as a desktop and laptop.
I think using an HTML forms interface is a good way to produce easy to use, interactive applications. I hope this example will demonstrate some of the possibilities. Let me know what you think.
Note: the gist above is now outdated. I have made a number of improvements since this initial post. Please use the newer gist shown in my second post, below.
Larry, great idea. Thanks for sharing!
One way to improve your code would be to use string.Template's substitute method, which is a preferred way to do string replacements in Python.
Thanks, @mcsquaredjr. I see string.replace is deprecated now. Unfortunately, using string.Template's substitute method doesn't work as neatly in some cases. I have re-written it, though, using substitute, which makes for longer (but perhaps more readable) code. Here's the link to the new version for those who might prefer it:
P.S. I cleaned up the HTML and styling a bit in this version as well.
hwm61 last edited by
@webvex, thank you for sharing. Very useful example.
I have created another version of my interactive form example. This one uses an external module to create the strings for some of the HTML form elements (text box, selects, radios, checkbox). Otherwise, it runs and operates the same.
If you don't like the idea of requiring a second file, the functions could be easily added to a single script––although, a separate module is obviously better for reuse in multiple scripts. Either way, using functions to generate some of the HTML allows for a much simpler and easier to read HTML section, and also allows you to populate the elements at run-time (e.g. from a database/web service, file, etc.).
The idea behind the module is sort of a mini framework for simple forms-based applications. I'm not holding my breath for something like Django to be adapted for Pythonista, but it isn't very difficult to create rudimentary web applications with easy-to-use, touch–friendly interfaces.
Here is the new application script:
And here is the accompanying module:
Larry, inspired by your example, I put together another interactive form example:
This script creates normalized multimarkdown tables. Unlike your code, my script builds html code using bs4. I think, this approach is more flexible as it allows structural html modifications.
Hope it is useful.
Very impressive. I'm still just learning Python and playing with the basics, although Beautiful Soup intrigues me. I will definitely look into it when/if I work with XLM, etc.
One suggestion would be to have the entire interface run inside the browser window, instead of switching from the console for input over to the browser for output. That would be less confusing and you could run it from any other computer on the same network. It's a very cool idea, though.
I'm also glad to see people working on productivity applications. (Multimarkdown tables are a bear to write manually.) I really think apps like Pythonista have great potential for that sort of thing.
Thanks for sharing!
P.S. I also finally figured out that the following will automatically stop the script when the browser closes:
webbrowser.open('http://localhost', stop_when_done = True)
Thanks, Larry. I'm glad if you found my code useful. I will take your suggestions into consideration in my next update. BTW, stop_when_done is really cool.
I looked at your code and Beautiful Soup a bit more today, and I agree that it is a more flexible approach (although it appears BS is geared more toward navigating/deconstructing existing HTML/XML documents). It would probably be a good strategy for a complex application with multiple screens or dynamic page elements.
I'm a bit old school, and I like to keep everything as simple as possible. For me, and the stuff I do, it's easier to just write (and read/maintain) most of the HTML as a string. I have written functions to generate the selects, radios, etc., though, which saves quite a bit of HTML string bulk and allows creating them from lists.
Going the BS route means creating the whole HTML document piece-by-piece. I suppose the decision comes down to whether you have more static or more dynamic elements. Or, maybe there's a hybrid solution, which seems likely—perhaps create a template of the page as a string and then use BS to manipulate only the dynamic parts.
Either way, these types of browser-based form applications are quite useful, and not that difficult to create. Hopefully, we'll see more development and ideas like this.
I agree -- simplicity is important. It just happened that writing Python for me is easier than wringing HTML :). I also think the hybrid solution might really be optimal. It would also be cool to write a library that renders html by parsing a simple configuration file (I did not check this, but I have a feeling something similar should exist).
Anyways, Pythonista is really quite good for interactive productivity apps, and it completely changed the way I use my iPad. I'm a development manager and I seriously consider ditching my laptop for good. Having such libraries as xmlrpc provides enormous flexibility, and, I'm sure, we will see new cool productivity apps written in Pythonista soon.
Once again, thanks for your inspirational ideas.
What's a laptop? Seriously, mine hasn't moved more than a few feet in over a year. I've had iPads since the original, and I've done all my Pythonista coding on a mini. It's quite a lifestyle change to be able to write code anywhere, waiting for an appointment, etc., places you wouldn't even have a laptop.
I think Ole has a winner here, if he keeps it up. I worry it doesn't bring in enough money for him, though, and he has other projects. I would like to see it get more visibility. I think there are a lot of people who want/need custom applications, that can be easily distributed (for free) and quickly tweaked, but eschew the whole App Store rigmarole. Most organizations have a ton of these sort of customized scripts and in-house applications that shouldn't have to pass through Apple. More and more individuals, bloggers, etc., need personalized workflows as well.
It will be interesting to see where apps like Pythonista and ScriptKit go, and whether Apple loosens the rules or gets in the game itself.
Yes, that would be interesting. Let's hope that Ole will keep up and let help him by rating Pythonista in the App Store.
eliskan175 last edited by
This is a great example and I can see how easily it would be now to access websites and make interactive website based apps through Pythonista.
I have always done my website parsing using strings. I have some experience with the process since I used to write programs to study and parse marketplace data in several games I played on. The problem is that parsing scripts had to be designed specially for the websites they study.
Honestly I never heard of BeautifulSoup until I got Pythonista. But this submission demonstrates that I could easily write an app for any web-based game, or genuine marketplace, or forum, or ANYTHING, with ease.
Great example and well worth the time to study for anyone who's interested with interacting to the world wide web via apps!
I also agree with the posts above. Pythonista needs more publicity. This is a great app. Get the word out, especially to other Python programmers. If the app gets enough support, the developer will have a good reason to make it better :)
Landyquack38 last edited by
New to Pythonista but old to Python. Stunningly useful app on an iPad2.
Been following this thread as a means to build UI for a prototype medical data collection form. Although web interface not ideal, understand that wxPython, iOS native controls all largely blocked by Apple so best available option for now.
Thought I'd throw bottle (import bottle dir(bottle)) into the mix... It's in Pythonista by default and makes REST based web interfaces trivial and has templating libs.
Need to find a way to create a web browser from within a bottle based app (thread?) but does Ajax and much that would be useful for interactive interface like the google search predictor etc.
Hope this helps someone
omz last edited by
@Landyquack You can start the web browser via <code>webbrowser.open(...)</code> <em>before</em> you start the (blocking) bottle server. Opening the web browser is slightly delayed, so by the time it shows up, the server should typically be running already.
Landyquack38 last edited by
Thanks for this - most of the time the browser beat the server but occasionally it didn't so bunged the browser into a threading.Timer() which solved things.
As a solution, it's a bit kludgy. Sometimes closing the webbrowser closes the whole script, sometimes it doesn't.
Had a look at what's possible within Scene - only at early stages but this may interest - http://omz-software.com/pythonista/forums/discussion/comment/715#Comment_715
gregthegeek last edited by
@Landyquack, I am very interested to see what come of this. (your GUI tests) I tested your Gists a little, nice to see. What I'd love , as with you, is a UI kit or something like that. I could really use that for whipping up quick-n-dirty , data-based apps for myself or clients. But I am not interested in running a local web server and using web forms. If I were to do that, I'd rather just make a normal web app.
I tried playing with ScriptKit and did manage to get some JSON forms and output working, but I like Python better, and I like the libs available too. But more importantly, I like the forums and user base! I also am tinkering with Codea, its cool, but no UI components, and if I have to build any, I'd rather use Python.
Keep us posted on your GUI work, sounds cool!
thierry.chich last edited by
I liked this idea when I read it. I have found an other way to implement it. Using pipista, I just installed bottle, a small framework, and it is really easy to write simple code that launch both the webserver and the webbrowser. It is a simpler way to write it, and a lot more powerfull (you can use templates, route, etc.).
I will try to post the sample script, but I don't know how to post something on gist.github from pythonista. I will look up.
I just succeeded to publish a file this way:
ccc last edited by
Bottle (but not Flask) is built into the current Pythonista so the pipista install step is not required for bottle.
Lately I have been doing a bit of Interactive Forms work in Pythonista and one gotcha that I see is that the bottle server keeps running even after the logic of your script has ended. You have to manually click the stop script button after your script logic completes to stop the bottle server (or you can wait for it to timeout on its own). Adding the Pythonista-only stop_when_done=True parameter to your last call to webbrowser.open() will gracefully shutdown the bottle server.
I posted a change request to your github code above so you could see this proposed change in action.
**NOTE: corrected parameter based on onionradish's comment below.
onionradish last edited by
As a note to omz, Bottle's inclusion isn't documented and should be. It's a great mini-framework for web apps, and likely isn't getting as much use as it should. I discovered Bottle independently a few weeks ago and installed it on my device manually. I did a double-take after reading ccc's reply that it's already included.
Regarding the Pythonista-only 'stop_when_done' option (ccc linked to and made the github change correctly but typo'd above), you can use os.name to optionally add the parameter so your script will run on the desktop without throwing an error. This is handy if you do development or testing on the desktop before copying the script to your device.
if os.name is 'posix': webbrowser.open('http://localhost:8080', stop_when_done=True) else: webbrowser.open('http://localhost:8080')