- 论坛徽章:
- 0
|
![]()
Search:
Wiki Navigation
File Upload Tutorial
¶
TurboGears
0.8a3
This 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:
- installed TG
- completed the previous tutorial
- are ready to add to that tutorial
Here 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:
- ui for displaying the files (we'll use templates for all the common stuff)
- ui for uploading/downloading the files
- state issues : we don't want to upload a file to a page that doesn't exist yet
Rather 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.
BTW - you don't have to copy and paste from this page, there are zip files attached...just grab the real thing, amigo.
-Todd
Update the DB Tables
¶
We 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:
stop the server
drop the existing tables
- tg-admin sql drop page
- tg-admin sql drop uploadedfile
your new model.py 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, length=100)
abspath = StringCol()
size = IntCol()
referenced_in_pages = RelatedJoin('Page')
create the new tables
Add the 'upload' Method
¶
Here 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:
Add upload directory to the cfg file
#def.cfg
[global]
# Upload dir
wiki.uploads="./uploads"
Add upload dir check to controller, create it if nec.
#controller.py
#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):
os.makedirs(UPLOAD_DIR)
Add the 'upload' method (remember meat and potatoes)
#controller.py
@turbogears.expose()
def upload(self, upload_file, pagename, new, **keywords):
try:
p = Page.byPagename(pagename)
except SQLObjectNotFound:
turbogears.flash("Must save page first")
raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename))
data = upload_file.file.read()
target_file_name = os.path.join(os.getcwd(),UPLOAD_DIR,upload_file.filename)
try:
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')
f.write(data)
f.close()
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)
Page.byPagename(pagename).addUploadedFile(u)
raise cherrypy.HTTPRedirect(turbogears.url("/%s" % pagename))
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: try:
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
¶
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.
#page.kid
filename:
Add the goo to display the file listings
¶
Here is the code:
Attached Files:
Filenamehere.
Add this code to page.kid and edit.kid
I've appended to this tutorial my notes for generalizing this with templates (see below)
Add the 'download' method
¶
cherrypy.lib.cptools.serveFile makes this super simple:
#controller.py
@turbogears.expose()
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
¶
#controller.py
@turbogears.expose(html="toddswiki.templates.page")
def index(self, pagename="FrontPage"):
try:
page = Page.byPagename(pagename)
uploads = [item.filename for item in page.attached_files]
except SQLObjectNotFound:
raise cherrypy.HTTPRedirect(turbogears.url("/notfound",pagename=pagename))
try:
content = publish_parts(page.data, writer_name="html")["html_body"]
except:
content = page.data
root = str(turbogears.url("/"))
content = wikiwords.sub(r'\1' % root, content)
content = content.encode("utf8")
return dict(data=content, pagename=page.pagename, uploads=uploads)
Generalize the File listing with Kid Templates (inheritance/matching)
¶
Make the following changes to get this working:
#master.kid
#page.kid / edit.kid
#includes.kid
Attached Files:
Filenamehere.
For more details, see:
Attachments
wiki.zip
(30.4 kB) -full files for the
FileUploadTutorial
, added by GreenTea on 10/20/05 18:14:28.
Download in other formats:
![]()
Powered by
Trac 0.9.4
By
Edgewall Software
.
Visit the Trac open source project at
http://trac.edgewall.com/
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/3176/showart_147038.html |
|