Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 1 and Version 2 of FileUploadTutorial


Ignore:
Timestamp:
10/21/05 16:51:36 (14 years ago)
Author:
GreenTea <tgreenwoodgeer@…>
Comment:

Fleshed out some comments, added templating of file listing

Legend:

Unmodified
Added
Removed
Modified
  • FileUploadTutorial

    v1 v2  
    22TurboGears 0.8a3 
    33 
    4 This is a follow up to the existing 20 minute wiki: http://turbogears.org/docs/wiki20/index.html. Note, I am writing this after creating this, and looking at my code and the email thread. Please make changes at will if I have slipped up.  
     4This is a follow up to the existing 20 minute wiki: http://turbogears.org/docs/wiki20/index.html. At this point, it is assumed that you have: 
     5 * installed TG 
     6 * completed the previous tutorial 
     7 * are ready to add to that tutorial 
    58 
    6 I'll add a zip of the full project directory, so don't feel like you have to copy and paste from this page...just grab the real thing, amigo. 
     9Here is what this tutorial is all about: File Uploads. After completing the above tutorial, I thought, 'gee, it'd be cool if I could upload files to the wiki'. And the way things go, one thing leads to another, and I wanted to download them, too. This introduces some issues, like: 
     10 * ui for displaying the files (we'll use templates for all the common stuff) 
     11 * ui for uploading/downloading the files 
     12 * state issues : we don't want to upload a file to a page that doesn't exist yet 
    713 
    8 TODO: template replace (see below) 
     14Rather than stepwise you thru my thought process and re-build this app like a real tutorial, I'll present the major issues along with the major chunks of code to address them.  
     15 
     16BTW - you don't have to copy and paste from this page, there are zip files attached...just grab the real thing, amigo. 
    917 
    1018-Todd 
    1119 
    1220== Update the DB Tables == 
     21We need to update the database to add a new table, the uploaded files table. This is a many to many relationship in my example. We'll have to drop our old tables and re-create these for the relationships to match. Here we go: 
     22 
    1323 1. stop the server 
    1424 1. drop the existing tables 
     
    4151 
    4252== Add the 'upload' Method == 
     53Here is the meat and potatoes. We add the upload method and a bunch of state logic. The idea is simple: we want to upload files and have them relate to a page. If a user uploads a previously uploaded file, we skip the upload, but we add the relationship to the db. So, multiple pages can reference a single uploaded file. And a single page can reference many files. Let's store these files in an app configured location: 
     54 
    4355 1. Add upload directory to the cfg file 
    4456 #def.cfg 
     
    5769    os.makedirs(UPLOAD_DIR)  
    5870}}} 
    59  1. Add the 'upload' method 
     71 1. Add the 'upload' method (remember meat and potatoes) 
    6072 #controller.py 
    6173 {{{ 
     
    88100                raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename)) 
    89101}}} 
    90  1. Note: the above uses the db to determine the page state (e.g. can we upload a page yet? no, not if the page doesn't exist yet) 
     102 1. Note: the above uses the db to determine the page state. If the page doesn't exist in the db, then we cannot relate an uploaded file to it: 
    91103 {{{ 
    92104                try: 
     
    98110 
    99111== Add 'upload' to the page.kid == 
    100  1. Initially, I was going to follow the footsteps of the previous tutorial, and use the hidden page variable 'new' to determine if the page had been created yet...but i had problems with this. Anyway, I think that state info is best queried from the db, anyway. Keep things simple. 
     112 1. Here's the form that calls the upload method (note we use a 'post'). Pretty simple. I have the hidden variable 'new' in here b/c I was going to use that for state tracking in the same way that the original tutorial did. For some reason, this wasn't working for me so I use the database instead, see above comment. 
    101113 #page.kid 
    102114 {{{ 
     
    118130}}} 
    119131 1. Add this code to page.kid and edit.kid  
    120  1. TODO: someone can help me with the template/replace stuff here 
     132 1. I've appended to this tutorial my notes for generalizing this with templates (see below) 
    121133 
    122134== Add the 'download' method == 
    123  1. cherrypy.lib.cptools.serveFile : this is pretty cool! 
     135 1. cherrypy.lib.cptools.serveFile makes this super simple: 
    124136 #controller.py 
    125137 {{{ 
     
    150162                return dict(data=content, pagename=page.pagename, uploads=uploads) 
    151163}}} 
     164 
     165== Generalize the File listing with Kid Templates (inheritance/matching) == 
     166Make the following changes to get this working: 
     167 
     168#master.kid 
     169{{{ 
     170<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
     171"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     172<?python import sitetemplate ?> 
     173<html 
     174xmlns="http://www.w3.org/1999/xhtml"xmlns:py="http://purl.org/kid/ns#" 
     175py:extends="sitetemplate, 'includes.kid'" 
     176}}} 
     177 
     178#page.kid / edit.kid 
     179{{{ 
     180        <div py:replace="attached_files('${filename}')"/> 
     181}}} 
     182 
     183#includes.kid 
     184{{{ 
     185<ul py:def="attached_files(filename)"> 
     186                Attached Files: 
     187                <li py:for="filename in uploads"><a 
     188href="./download?filename=${filename}" 
     189py:content="filename">Filenamehere.</a></li> 
     190</ul>  
     191}}} 
     192 
     193For more details, see: 
     194 * http://kid.lesscode.org/language.html#template-reuse-py-extends 
     195 * http://lesscode.org/projects/kid/wiki/IncludeSectionFromOtherTemplateRecipe