def save_doc(self, doc, encode=False, force_update=False, **params): """ Save a document. It will use the `_id` member of the document or request a new uuid from CouchDB. IDs are attached to documents on the client side because POST has the curious property of being automatically retried by proxies in the event of network segmentation and lost responses. @param doc: dict. doc is updated with doc '_id' and '_rev' properties returned by CouchDB server when you save. @param force_update: boolean, if there is conlict, try to update with latest revision @param encode: Encode attachments if needed (depends on couchdb version) @return: new doc with updated revision an id """ if '_attachments' in doc and encode: doc['_attachments'] = encode_attachments(doc['_attachments']) headers = params.get('headers', {}) headers.setdefault('Content-Type', 'application/json') params['headers'] = headers if '_id' in doc: docid = escape_docid(doc['_id']) try: resp = self.res.put(docid, payload=json.dumps(doc), **params) except ResourceConflict: if not force_update: raise rev = self.last_rev(doc['_id']) doc['_rev'] = rev resp = self.res.put(docid, payload=json.dumps(doc), **params) else: json_doc = json.dumps(doc) try: doc['_id'] = self.uuids.next() resp = self.res.put(doc['_id'], payload=json_doc, **params) except ResourceConflict: resp = self.res.post(payload=json_doc, **params) json_res = resp.json_body doc1 = {} for a, n in aliases.items(): if a in json_res: doc1[n] = json_res[a] doc.update(doc1) return doc
def encode_params(params): """ encode parameters in json if needed """ _params = {} if params: for name, value in params.items(): if value is None: continue if name in ("key", "startkey", "endkey") or not isinstance(value, basestring): value = json.dumps(value).encode("utf-8") _params[name] = value return _params
def view(self, view_name, **params): try: dname, vname = view_name.split("/") path = "/_design/%s/_view/%s" % (dname, vname) except ValueError: path = view_name if "keys" in params: keys = params.pop("keys") return self.post(path, json.dumps({"keys": keys}, **params)).json_body return self.get(path, **params).json_body
def encode_params(params): """ encode parameters in json if needed """ _params = {} if params: for name, value in params.items(): if value is None: continue if name in ('key', 'startkey', 'endkey') \ or not isinstance(value, basestring): value = json.dumps(value).encode('utf-8') _params[name] = value return _params
def view(self, view_name, **params): try: dname, vname = view_name.split("/") path = "/_design/%s/_view/%s" % (dname, vname) except ValueError: path = view_name if "keys" in params: keys = params.pop("keys") return self.res.post(path, json.dumps({"keys": keys}, **params)).json_body return self.res.get(path, **params).json_body
def save_docs(self, docs, all_or_nothing=False, use_uuids=True): """ Bulk save. Modify Multiple Documents With a Single Request @param docs: list of docs @param use_uuids: add _id in doc who don't have it already set. @param all_or_nothing: In the case of a power failure, when the database restarts either all the changes will have been saved or none of them. However, it does not do conflict checking, so the documents will. @return doc lists updated with new revision or raise BulkSaveError exception. You can access to doc created and docs in error as properties of this exception. """ def is_id(doc): return '_id' in doc if use_uuids: noids = [] for k, g in itertools.groupby(docs, is_id): if not k: noids = list(g) for doc in noids: nextid = self.uuids.next() if nextid: doc['_id'] = nextid payload = {"docs": docs} if all_or_nothing: payload["all-or-nothing"] = True # update docs res = self.res.post('/_bulk_docs', payload=json.dumps(payload), headers={'Content-Type': 'application/json'}) json_res = res.json_body errors = [] for i, r in enumerate(json_res): if 'error' in r: doc1 = docs[i] doc1.update({'_id': r['id'], '_rev': r['rev']}) errors.append(doc1) else: docs[i].update({'_id': r['id'], '_rev': r['rev']}) if errors: raise BulkSaveError(docs, errors)
def save_docs(self, docs, all_or_nothing=False, use_uuids=True): """ Bulk save. Modify Multiple Documents With a Single Request @param docs: list of docs @param use_uuids: add _id in doc who don't have it already set. @param all_or_nothing: In the case of a power failure, when the database restarts either all the changes will have been saved or none of them. However, it does not do conflict checking, so the documents will @return doc lists updated with new revision or raise BulkSaveError exception. You can access to doc created and docs in error as properties of this exception. """ def is_id(doc): return '_id' in doc if use_uuids: noids = [] for k, g in itertools.groupby(docs, is_id): if not k: noids = list(g) for doc in noids: nextid = self.uuids.next() if nextid: doc['_id'] = nextid payload = { "docs": docs } if all_or_nothing: payload["all-or-nothing"] = True # update docs res = self.res.post('/_bulk_docs', payload=json.dumps(payload), headers={'Content-Type': 'application/json'}) json_res = res.json_body errors = [] for i, r in enumerate(json_res): if 'error' in r: doc1 = docs[i] doc1.update({'_id': r['id'], '_rev': r['rev']}) errors.append(doc1) else: docs[i].update({'_id': r['id'], '_rev': r['rev']}) if errors: raise BulkSaveError(docs, errors)