add basic attachment support to the doc_model twisty
authorMark Hammond <>
Mon, 23 Mar 2009 14:08:42 +1100
changeset 112 b2f2984dd6482fbd7d4f8b13f937aaf03288b198
parent 111 b0340c2821da37ecd100912692f3876ed6fa1806
child 113 e07ebe3f1e17ed502d2dc052bc753b6146d33d73
push id1
push userroot
push dateWed, 08 Apr 2009 01:46:05 +0000
add basic attachment support to the doc_model
--- a/server/python/junius/
+++ b/server/python/junius/
@@ -68,16 +68,23 @@ class CouchDB(paisley.CouchDB):
     def openView(self, *args, **kwargs):
         # The base class of this returns the raw json object - eg:
         # {'rows': [], 'total_rows': 0}
         # *sob* - and it also doesn't handle encoding options...
         return super(CouchDB, self).openView(*args, **_encode_options(kwargs)
+    def openDoc(self, dbName, docId, revision=None, full=False, attachment=""):
+        # paisley appears to use an old api for attachments?
+        if attachment:
+            uri = "/%s/%s/%s" % (dbName, docId, attachment)
+            return  self.get(uri)
+        return super(CouchDB, self).openDoc(dbName, docId, revision, full)
 def get_db(couchname="local", dbname=_NotSpecified):
     dbinfo = config.couches[couchname]
     if dbname is _NotSpecified:
         dbname = dbinfo['name']
     key = couchname, dbname
         return DBs[key]
     except KeyError:
@@ -93,40 +100,46 @@ def quote_id(doc_id):
 class DocumentModel(object):
     """The layer between 'documents' and the 'database'.  Responsible for
        creating the unique ID for each document (other than the raw document),
        for fetching documents based on an ID, etc
     def __init__(self, db):
         self.db = db
-    def open_document(self, doc_id):
-        """Open the specific extension's document for the given ID"""
-        return self.db.openDoc(quote_id(doc_id)).addBoth(self._cb_doc_opened)
+    def open_document(self, doc_id, **kw):
+        """Open the specific document, returning None if it doesn't exist"""
+        return self.db.openDoc(quote_id(doc_id), **kw).addBoth(self._cb_doc_opened)
     def _cb_doc_opened(self, result):
         if isinstance(result, Failure):
             if result.value.status != '404': # not found
             result = None # indicate no doc exists.
         return result
-    def create_raw_document(self, docid, doc, doc_type, account):
+    def create_raw_document(self, docid, doc, doc_type, account, attachments=None):
         assert '_id' not in doc # that isn't how you specify the ID.
         assert '!' not in docid, docid # these chars are special.
         assert 'raindrop_account' not in doc, doc # we look after that!
         doc['raindrop_account'] = account.details['_id']
         assert 'type' not in doc, doc # we look after that!
         doc['type'] = doc_type
         assert 'raindrop_seq' not in doc, doc # we look after that!
         doc['raindrop_seq'] = get_seq()
+        # XXX - for small blobs this is good (we get the attachment in the
+        # same request as the doc).  For large blobs this is bad, as we
+        # base64 encode the data in memory before sending it.
+        if attachments:
+            self.db.addAttachments(doc, attachments)
         # save the document.
         logger.debug('create_raw_document saving doc %r', docid)
         return self.db.saveDoc(doc, docId=quote_id(docid),
     def _cb_saved_document(self, result):