GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing webwareforpython.github.io — Beginner Tutorial — Webware for Python 3 3.1.0 documentation Beginner Tutorial¶In this tutorial we will show how to write a very simple Webware application. Again, we assume that you have Webware for Python 3 already installed in a virtual environment, and activate the virtual environment as explained in the chapter on Installation. Creating a Working Directory¶We’ll first set up a directory dedicated to your application, the so-called “application working directory”. Change into your home directory or wherever you want to create that working directory. We recommend creating the virtual environment and the application working directory as siblings in a dedicated base directory, which can be the home directory of a dedicated user that acts as “owner” of the application. Then run this command: webware make -c Context -l Lib WebwareTest You’ll now have a directory “WebwareTest” in the current directory. Inside this directory will be several subdirectories and a couple files. The directories of interest are For more information about the working directory and setting up the file structure for your application, see Application Development. Changing the Webware Configuration¶For the most part the configuration is fine, but we’ll make a couple changes to make it easier to develop. For more information on configuration see the chapter on Configuration. One change you may want to make to allow you to use more interesting URLs. In ExtraPathInfo = True Otherwise the settings should be appropriate already for our purposes. Creating and Understanding the Servlet¶Webware’s core concept for serving pages is the servlet. This is a class that creates a response given a request. The core classes to understanding the servlet are While there are several levels you can work on while creating your servlet, in this tutorial we will work solely with subclassing the A Brief Introduction to the Servlet¶Each servlet is a plain Python class. There is no Webware magic (except perhaps for the level one import module based on URL spell). PSP has more magic, but that’s a topic for another chapter. An extremely simple servlet might look like: from Page import Page class MyServlet(Page): def title(self): return 'My Sample Servlet' def writeContent(self): self.write('Hello world!') This would be placed in a file Webware calls the servlet like this:
You only have to override the portions that you want to. It is not uncommon to only override the You’ll notice a file A Photo Album¶If you look online, you’ll see a huge number of web applications available for an online photo album. The world needs one more! You will need the Pillow library installed for this example. If you installed Webware for Python 3 with the “examples” or “test” option, as recommended in the chapter on Installation, this should be already the case. First we’ll use this library to find the sizes of the images, and later we will use it to create thumbnails. We’ll develop the application in two iterations. Iteration 1: Displaying files¶For simplicity, we will store image files in a subdirectory For the first iteration, we’ll display files that you upload by hand to the We do this with two servlets – one servlet import os from PIL import Image # this is from the Pillow library from Page import Page # the base class for web pages dir = os.path.join(os.path.dirname(__file__), 'Pics') class Main(Page): def title(self): # It's nice to give a real title, otherwise "Main" would be used. return 'Photo Album' def writeContent(self): # We'll format these simply, one thumbnail per line: for filename in os.listdir(dir): im = Image.open(os.path.join(dir, filename)) w, h = im.size # Here we figure out the scaled-down size of the image, # so that we preserve the aspect ratio. We'll use fake # thumbnails, where the image is scaled down by the browser. w, h = int(round(w * 100 / h)), 100 # Note that we are just using f-strings to generate the HTML. # There's other ways, but this works well enough. # We're linking to the View servlet which we'll show later. # Notice we use urlencode -- otherwise we'll encounter bugs if # there are file names with spaces or other problematic chars. url = self.urlEncode(filename) self.writeln(f'<p><a href="View?filename={url}">' f'<img src="Pics/{url}" width="{w}" height="{h}"></a></p>') The servlet req = self.request() self.write(req.field('username')) If you need the request only once, you can write it even more compactly: field = self.request().field self.write(field('username')) So here is our complete import os from PIL import Image from Page import Page dir = os.path.join(os.path.dirname(__file__), 'Pics') class View(Page): def title(self): return 'View: ' + self.htmlEncode(self.request().field('filename')) def writeContent(self): filename = self.request().field('filename') im = Image.open(os.path.join(dir, filename)) wr = self.writeln wr('<div style="text-align:center">') wr(f'<h4>{filename}</h4>') url = self.urlEncode(filename) w, h = im.size wr(f'<img src="Pics/{url}" width="{w}" height="{h}">') wr('<p><a href="Main">Return to Index</a></p>') wr('</div>') Iteration 2: Uploading Files¶That was fairly simple – but usually you want to upload files, potentially through a web interface. Along the way we’ll add thumbnail generation using Pillow, and slightly improve the image index. We’ll generate thumbnails kind of on demand, so you can still upload files manually – thumbnails will be put in the directory import os from PIL import Image from Page import Page baseDir = os.path.dirname(__file__) picsDir = os.path.join(baseDir, 'Pics') thumbsDir = os.path.join(baseDir, 'Thumbs') class Main(Page): def title(self): return 'Photo Album' def writeContent(self): # The heading: self.writeln(f'<h1 style="text-align:center">{self.title()}</h1>') # We'll format these in a table, two columns wide self.writeln('<table width="100%">') col = 0 # will be 0 for the left and 1 for the right column filenames = os.listdir(picsDir) # We'll sort the files, case-insensitive filenames.sort(key=lambda filename: filename.lower()) for filename in filenames: if not col: # left column self.write('<tr style="text-align:center">') thumbFilename = os.path.splitext(filename) thumbFilename = '{}-tn{}'.format(*thumbFilename) if not os.path.exists(os.path.join(thumbsDir, thumbFilename)): # No thumbnail exists -- we have to generate one if not os.path.exists(thumbsDir): # Not even the Thumbs directory exists -- make it os.mkdir(thumbsDir) im = Image.open(os.path.join(picsDir, filename)) im.thumbnail((250, 100)) im.save(os.path.join(thumbsDir, thumbFilename)) else: im = Image.open(os.path.join(thumbsDir, thumbFilename)) url = self.urlEncode(filename) w, h = im.size size = os.stat(os.path.join(picsDir, filename)).st_size self.writeln(f'<td><p><a href="View?filename={url}">' f'<img src="Pics/{url}" width="{w}" height="{h}"></a></p>' f'<p>Filename: {filename}<br>Size: {size} Bytes</p>') if col: # right column self.writeln('</tr>') col = not col self.write('</table>') self.write('<p style="text-align:center">' '<a href="Upload">Upload an image</a></p>') In a real application, you would probably style the image more nicely using CSS, maybe using a flexbox or grid layout instead of using a table. You can add a CSS style sheet for this purpose with the The We’ll add an import os from Page import Page dir = os.path.join(os.path.dirname(__file__), 'Pics') class Upload(Page): def writeContent(self): if self.request().hasField('imageFile'): self.doUpload() return self.writeln(''' <h3>Upload your image:</h3> <form action="Upload" method="post" enctype="multipart/form-data"> <input type="file" name="imageFile"> <input type="submit" value="Upload"> </form>''') def doUpload(self): file = self.request().field('imageFile') # Because it's a file upload, we don't get a string back. # So to get the value we do this: filename, contents = file.filename, file.value open(os.path.join(dir, filename), 'wb').write(contents) url = 'View?filename=' + self.urlEncode(filename) self.response().sendRedirect(url) Using the “upload” button it should now be possible to upload images to the |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |