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

Version 1 (modified by GreenTea <tgreenwoodgeer@…>, 14 years ago) (diff)

initial add...

File Upload Tutorial

TurboGears 0.8a3

This is a follow up to the existing 20 minute wiki: 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.

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.

TODO: template replace (see below)


Update the DB Tables

  1. stop the server
  2. drop the existing tables
    • tg-admin sql drop page
    • tg-admin sql drop uploadedfile
  3. your new
    from sqlobject import *
    from turbogears.database import PackageHub
    hub = PackageHub("toddswiki")
    __connection__ = hub
    # class YourDataClass(SQLObject):
    #     pass
    class Page(SQLObject):
            pagename = StringCol(alternateID=True, length=30)
            data = StringCol()
            attached_files = RelatedJoin('UploadedFile')
    class UploadedFile(SQLObject):
            filename = StringCol(alternateID=True)
            abspath = StringCol()
            size = IntCol()
            referenced_in_pages = RelatedJoin('Page')
  4. create the new tables
    • tg-admin sql create

Add the 'upload' Method

  1. Add upload directory to the cfg file #def.cfg
    # Upload dir
  2. Add upload dir check to controller, create it if nec.
    #default upload dir to ./uploads
    UPLOAD_DIR = cherrypy.config.get("wiki.uploads", os.path.join(os.getcwd(),"uploads"))
    if not os.path.exists(UPLOAD_DIR):
  3. Add the 'upload' method
    	def upload(self, upload_file, pagename, new, **keywords):
    			p = Page.byPagename(pagename)
    		except SQLObjectNotFound:
    			turbogears.flash("Must save page first")
    			raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename))
    		while True:
    			data =
    			if not data:
    			total_data += data
    		target_file_name = os.path.join(os.getcwd(),UPLOAD_DIR,upload_file.filename)
    			u =  UploadedFile.byFilename(upload_file.filename)
    			turbogears.flash("File already uploaded: %s is already at %s" %  (upload_file.filename, target_file_name))
    		except SQLObjectNotFound:
    			f = open(target_file_name, 'w')
    			turbogears.flash("File uploaded successfully: %s saved as : %s" % (upload_file.filename, target_file_name))
    			u = UploadedFile(filename=upload_file.filename, abspath=target_file_name, size=0)
    		raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename))
  4. 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)
    			p = Page.byPagename(pagename)
    		except SQLObjectNotFound:
    			turbogears.flash("Must save page first")
    			raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename))

Add 'upload' to the page.kid

  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. #page.kid
    	<form action="upload" method="post" enctype="multipart/form-data">
    		<input type="hidden" name="pagename" py:attrs="value=pagename"/>
    		<input type="hidden" name="new" value="${new}"/>
    		filename: <input type="file" name="upload_file"/><br/>
    		<input type="submit" name="submit_upload" value="Upload"/>

Add the goo to display the file listings

  1. Here is the code:
    		Attached Files:
    		<li py:for="filename in uploads"><a href="/download?filename=${filename}" py:content="filename">Filenamehere.</a></li>
  2. Add this code to page.kid and edit.kid
  3. TODO: someone can help me with the template/replace stuff here

Add the 'download' method

  1. cherrypy.lib.cptools.serveFile : this is pretty cool!
    	def download(self, filename):
    		uf = UploadedFile.byFilename(filename)
    		return cherrypy.lib.cptools.serveFile(uf.abspath, "application/x-download", "attachment", uf.filename)

Add error handling to the index method, just in case publish parts barfs

	def index(self, pagename="FrontPage"):
			page = Page.byPagename(pagename)
			uploads = [item.filename for item in page.attached_files]
		except SQLObjectNotFound:
			raise cherrypy.HTTPRedirect(turbogears.url("/notfound",pagename=pagename))
			content = publish_parts(, writer_name="html")["html_body"]
			content =

		root = str(turbogears.url("/"))
		content = wikiwords.sub(r'<a href="%s\1">\1</a>' % root, content)
		content = content.encode("utf8")
		return dict(data=content, pagename=page.pagename, uploads=uploads)