def test_nextid_id_empty_collection(self): '''Doc this ''' db = self.g['db'] generic = controllers.Generic(self.g) coll = db['cnts'] response = nextId(coll) assert response['status'] == 200 assert response['nextId'] == 1
def test_nextid_id_empty_collection(self): """Doc this """ db = self.g["db"] generic = controllers.Generic(self.g) coll = db["cnts"] response = nextId(coll) assert response["status"] == 200 assert response["nextId"] == 1
def post(self, **kwargs): '''Insert a doc newDocTmp: Initialize a temp (tmp) doc if no OID and no data. cloneDocTmp: Clone to a temp doc if OID and no isTmp flag set. upsertDocTmp: Update or Insert temp doc to base collection if OID and isTmp is set. insertDoc: Insert a new doc if no OID and there are more attributes than _c. ''' db = self.db response = {} docs = [] status = 200 usrOID = self.usr['OID'] docs_to_post = kwargs['docs'] post_errors = [] total_errors = 0 for doc in docs_to_post: errors = {} doc_info = {} # required attribute _c = doc['_c'] # shortcut doc_keys = doc.keys() modelClass = getattr(models, _c) _id = doc['_id'] if '_id' in doc_keys else None where = {'_id': ObjectId(_id)} if _id else None attrNam = doc['attrNam'] if 'attrNam' in doc_keys else None attr_c = doc['attr_c'] if attrNam else None attrVal = doc['attrVal'] if attrNam else None collNam = modelClass.meta['collection'] collTmp = db[collNam + '_tmp'] coll = db[collNam] # if _ id is passed, it directs that a temp doc be initialized and inserted into the appropriate Tmp (temp) collection. # if an _id IS passed, it directs that the doc passed in be validated and inserted in the base collection and the temp doc in the temp collection be deleted. # if attrNam, posting a new value to a listtype attribute/field if attrNam: for elem in attrVal: modelClass = getattr(models.embed, attr_c) model = modelClass() for k,v in elem.iteritems(): setattr(model, k, v) resp = nextEId(doc, attrNam) doc = resp['doc'] # model.eIds = doc['eIds'] model.eId = resp['eId'] if hasattr(model, 'vNam') and 'dNam' in model._fields and not model.dNam: model.dNam = model.vNam # generate a slug if slug is empty if 'slug' in model._fields and 'dNam' in model._fields and not model.slug: model.slug = slugify(model.dNam, coll) # set dNamS if used: # if dNamS is empty, set to value of slug if 'dNamS' in model._fields and not model.dNamS: if hasattr(model, 'vNamS'): model.dNamS = model.vNamS else: model.dNamS = model.slug embedDoc = doc_remove_empty_keys(to_python(model, allow_none=True)) doc_errors = validate(modelClass, embedDoc) if doc_errors: total_errors += doc_errors['count'] post_errors.append(doc_errors) continue embedDoc['_c'] = attr_c # logit update embedDoc = logit(self.usr, embedDoc, method='post') collTmp.update(where, {"$push": { attrNam: embedDoc}, "$set": {'eIds': doc['eIds']}} ) doc_info['doc'] = embedDoc docs.append(doc_info) # http://docs.mongodb.org/manual/applications/update/ # { $set: { 'emails.$.eId': 2 } response['total_inserted'] = len(docs) if post_errors: response['total_invalid'] = len(post_errors) response['errors'] = post_errors response['total_errors'] = total_errors status = 400 else: response['total_invalid'] = 0 response['docs'] = docs return {'response': response, 'status': status} # Initialize a temp (tmp) doc if no OID and no data. elif not '_id' in doc_keys and len(doc_keys) == 1: newDocTmp = True useTmpDoc = True # Clone to a temp doc if OID and no isTmp flag set. elif '_id' in doc_keys and not 'isTmp' in doc_keys and len(doc_keys) > 2: cloneDocTmp = True useTmpDoc = True # find source doc # set locked = True doc_cloned = coll.find_and_modify( query = {'_id':_id}, update = {"$set": {'locked': True}}, new = True ) # set cloned doc in tmp collection isTmp = True doc_cloned['isTmp'] = True # don't need locked set in tmp doc del doc_cloned['locked'] # clone/save doc to tmp collection # TODO properly handle exception try: collTmp.insert(doc_cloned) except: pass doc_info['doc'] = doc_cloned # TODO # should return a link to object according to good practice #doc_info['link'] = get_document_link(class_name, id) docs.append(doc_info) continue # Update temp doc to base collection if OID and isTmp is set. elif '_id' in doc_keys and 'isTmp' in doc_keys and doc['isTmp']: upsertDocTmp = True useTmpDoc = False tmp_doc = collTmp.find_one({'_id': _id}) # unset isTmp _id = tmp_doc['_id'] tmp_doc['locked'] = False del tmp_doc['_id'] del tmp_doc['isTmp'] # logit update tmp_doc = logit(self.usr, tmp_doc) # update original/source doc doc = coll.update({'_id': _id}, {"$set": tmp_doc}, upsert=True, safe=True) # remove tmp doc collTmp.remove({'_id': _id}) # though not necessary, to be consistant, return full doc doc = coll.find_one({'_id': _id}) doc_info['doc'] = doc docs.append(doc_info) continue # Insert a new doc if no OID and there are more attributes than _c. elif not '_id' in doc_keys and len(doc_keys) > 2: insertDoc = True useTmpDoc = False # need to cruz through all doc keys to handle arrays/listtype fields. # they need to be initialized according to the appropriate model and validated, etc. doc = initDocListTypes(doc, self.usr) # init model instance model = modelClass(**doc) # set isTemp model.isTmp = useTmpDoc and 'isTmp' in model._fields # try to generate dNam # if there is a vNam class property # if already has a value, use it if hasattr(model, 'vNam') and not useTmpDoc and 'dNam' in model._fields and not model.dNam: model.dNam = model.vNam # assign dId if 'dId' in model._fields and not model.dId: response = nextId(coll) if response['status'] == 200: model.dId = response['nextId'] else: # handle error condition pass # generate a slug if: # not a temp doc and slug is empty if 'slug' in model._fields and not useTmpDoc and not model.slug: model.slug = slugify(model.dNam, coll) # set dNamS if used: # not a temp doc and dNamS is empty, set to value of slug if 'dNamS' in model._fields and not useTmpDoc and not model.dNamS: model.dNamS = model.slug # do not validate if using temp doc if not useTmpDoc: doc_errors = validate(modelClass, doc) if doc_errors: total_errors += doc_errors['count'] post_errors.append(doc_errors) continue # modelClass stuffed in all available fields # let's remove all empty fields to keep mongo clean. doc = to_python(model, allow_none=True) # do not log if using temp doc #log date time user involved with this event if not useTmpDoc: doc = logit(self.usr, doc, 'post') doc['_c'] = _c doc_clean = doc_remove_empty_keys(doc) # posting an existing temp doc to base collection if _id: doc_clean['_id'] = str(_id) id = str(coll.insert(doc_clean)) # TODO properly handle exception try: collTmp.remove({'_id': _id}) except: pass # posting initialized temp doc else: # TODO properly handle exception try: coll.insert(doc_clean) except: pass doc_info['doc'] = doc_clean # TODO # should return a link to object according to good practice #doc_info['link'] = get_document_link(class_name, id) docs.append(doc_info) response['total_inserted'] = len(docs) if post_errors: response['total_invalid'] = len(post_errors) response['errors'] = post_errors response['total_errors'] = total_errors status = 400 else: response['total_invalid'] = 0 response['docs'] = docs return {'response': response, 'status': status}