Exemple #1
0
def SaveNaturopathy(self):
    code = 201
    status = False
    message = ""
    responseData = {}
    # todayDate = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    todayDate = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    ip_address = socket.gethostbyname(socket.gethostname())
    requestData = dict(request.json)
    # converting price in integer and id in objctect id

    # if requestData['accomodations'] != None:
    #     price = requestData['accomodations']
    #     for key in price:
    #         price[key] = int(price[key])

    #     requestData['accomodations'] = price
    # sys.exit();

    find_outlet = DB.find_one(tbl_v004_outlets,
                              {"_id": ObjectId(requestData['outlet_id'])})
    # print(requestData)

    if find_outlet:
        if requestData['naturopathy_id'] == "":
            del requestData['naturopathy_id']
            requestData["vendor_id"] = ObjectId(requestData["vendor_id"])
            requestData["outlet_id"] = ObjectId(requestData["outlet_id"])
            requestData["category_id"] = ObjectId(requestData["category_id"])
            requestData["business_type"] = "naturopathy"
            if requestData["sub_category_id"] == "other":
                requestData["sub_category_id"] == "other"
            else:
                requestData["sub_category_id"] = ObjectId(
                    requestData["sub_category_id"])
            requestData["recurring"] = False
            requestData['total_days'] = ""
            requestData["status"] = 1
            requestData["is_delete"] = 0
            requestData["created_by"] = ObjectId(requestData["user_id"])
            requestData["created_date"] = todayDate
            requestData["insert_ip"] = ip_address
            del requestData['user_id']
            act = DB.insert(tbl_v028_meditation_naturopathy, requestData)
            update_tour_steps = DB.update_one(
                tbl_v026_tour_steps, {"setup_service": True},
                {"vendor_id": ObjectId(requestData["vendor_id"])})
            responseData['naturopathy_id'] = act
            if act:
                code = 200
                status = True
                message = MSG_CONST.NATUROPATHY_INSERTED_SUCCESS
            else:
                code = 201
                status = False
                message = MSG_CONST.NATUROPATHY_INSERTED_FAILED

        else:
            requestData["vendor_id"] = ObjectId(requestData["vendor_id"])
            requestData["outlet_id"] = ObjectId(requestData["outlet_id"])
            requestData["category_id"] = ObjectId(requestData["category_id"])
            if requestData["sub_category_id"] == "other":
                requestData["sub_category_id"] == "other"
            else:
                requestData["sub_category_id"] = ObjectId(
                    requestData["sub_category_id"])
            # requestData["sub_category_id"] = ObjectId(requestData["sub_category_id"])
            requestData['naturopathy_id'] = ObjectId(
                requestData['naturopathy_id'])
            requestData["updated_by"] = ObjectId(requestData["user_id"])
            if requestData["type"] == "hourly":
                requestData["accomodations"] = []
            if requestData["type"] == "flexible":
                requestData["times"] = []
                if requestData["accomodations"] != []:
                    requestData['price'] = ""
            requestData["updated_date"] = todayDate
            requestData["updated_ip"] = ip_address
            del requestData['user_id']
            # del requestData['service_id']
            act = DB.update_one(tbl_v028_meditation_naturopathy, requestData,
                                {"_id": requestData["naturopathy_id"]})
            if act:
                code = 200
                status = True
                message = MSG_CONST.NATUROPATHY_UPDATED_SUCCESS
            else:
                code = 201
                status = False
                message = MSG_CONST.NATUROPATHY_UPDATED_FAILED
    response = output_json(responseData, message, status, code)
    logging.debug('SaveNaturopathy: {}'.format(response))
    return response
Exemple #2
0
                            }
                            userdb.insert(new_user_info)
                            user_object_id = userdb.find_one({"email": email})
                            user_object_id = user_object_id["_id"]
                            print(user_object_id)
                    else:
                        user_object_id = userdb.find_one({"email": email})
                        user_object_id = user_object_id["_id"]
                        print(user_object_id)

                # Company ID:
                default_id = companydb.find_one({"name": "Unknown_Company"})
                default_id = default_id["_id"]

                new_job_info = {
                    "user_id": ObjectId(f"{user_object_id}"),
                    "job_details": {
                        "url":
                        url,
                        "title":
                        position,
                        "country_id":
                        "GE",
                        "city":
                        location_id,
                        "industry":
                        category,
                        "views":
                        views,
                        "employment_type":
                        stack,
 def buscar_gabarito(self, id_prova):
     gabarito = self.provas.find_one({"_id": ObjectId(id_prova)})
     return gabarito['questoes']
 def test_get_tour_experiences(self):
     tour_id = ObjectId("5ec573d6fabc70e713595a94")
     result = self.app.get(f'/api/v1/tours/{tour_id}/experiences')
     self.assertIsNotNone(result)
Exemple #5
0
def post_add():
    '''
    status:
    0:草稿
    1:发布
    2:待审核
    3:审核未通过
    4:已删除
    5:自动审核通过
    :return:
    '''

    view_data = {
        'title': u'发表-{}'.format(config['title'].TITLE),
        'hint': '写点东西'
    }
    view_data['permission'] = Permission.ECP
    view_data['help'] = mdb_cont.db.posts.find_one({
        'type': u'帮助',
        'title': u'文章编辑帮助'
    })
    subject = request.args.get('subject')
    if subject == "tech":
        view_data['hint'] = '科技有趣'
    elif subject == "ART":
        view_data['hint'] = '音乐|艺术'
    elif subject == "sys":
        if not current_user.can(
                Permission.ADMINISTER) and not current_user.is_role(
                    Permission.ECP):
            abort(404)
        view_data['hint'] = '系统告示'

    if not subject in config['post'].SUBJECT:
        abort(404)
    else:
        form = EditPost(subject)

    if form.issue.data:
        if not form.title.data:
            flash({'type': 'w', 'msg': u'标题不能为空哦!'})
            form.s_type.data = form.s_type.data
            form.body.data = form.body.data
            return render_template('post/posts/edit.html',
                                   form=form,
                                   view_data=view_data)

        # if current_user.can(Permission.ECP):
        #     status = 1
        # else:
        #     status = 2
        status = 1
        # 封面图片
        img_url = post_img(form.body.data, form.s_type.data)
        form.body.data = edit_img_log_claer(form.body.data, None)
        tag_list = request.form.getlist("boolean_l")
        post = {
            'user_id': current_user.id,
            'title': form.title.data.strip(),
            'body': form.body.data,
            'tag': tag_list,
            'type': form.s_type.data,
            'img_url': img_url,
            'praise': 0,
            'praise_id': [],
            'pv': 0,
            'pv_id': [],
            'status': status,
            'time': time.time(),
            'update_time': time.time(),
            'is_been': 1,
            'subject': subject,
        }
        post_id = mdb_cont.db.posts.insert(post)
        post_cnt_update(current_user.id)
        if status == 1:
            flash({
                'msg':
                u'发表成功!首页|专栏可能延迟{}秒推出.'.format(config['cache_timeout'].POSTS),
                "type":
                's'
            })
            return redirect(url_for('post.show', post_id=post_id))
        else:
            return redirect(url_for('post.preview', post_id=post_id))

    elif form.draft.data:
        if not form.title.data:
            flash({'type': 'w', 'msg': u'标题不能为空哦!'})
            form.s_type.data = form.s_type.data
            form.body.data = form.body.data
            return render_template('post/posts/edit.html',
                                   form=form,
                                   view_data=view_data)
        tag_list = request.form.getlist("boolean_l")

        # 封面图片
        img_url = post_img(form.body.data, form.s_type.data)
        form.body.data = edit_img_log_claer(form.body.data, None)
        post = {
            'user_id': current_user.id,
            'title': form.title.data.strip(),
            'body': form.body.data,
            'tag': tag_list,
            'type': form.s_type.data,
            'img_url': img_url,
            'praise': 0,
            'praise_id': [],
            'pv': 0,
            'pv_id': [],
            'status': 0,
            'time': time.time(),
            'update_time': time.time(),
            'is_been': 0,
            'subject': subject,
        }
        post_id = mdb_cont.db.posts.insert(post)
        post_cnt_update(current_user.id, )
        return redirect(url_for('post.preview', post_id=post_id))

    # view_data
    view_data['tag_s'] = []
    tags = mdb_sys.db.type.find_one({'project': "post-tag", "subject": "tag"})
    if tags:
        view_data['tag_s'] = tags["type"]

    view_data['tag_u'] = []
    tags = mdb_cont.db.tag.find_one({'user_id': ObjectId(current_user.id)})
    if tags:
        view_data['tag_u'] = tags['tag']

    view_data['post'] = {'img_url': 'images/post_img/未分类_default.png'}
    return render_template('{}/post/edit.html'.format(Theme.THEME_NAME),
                           form=form,
                           view_data=view_data)
Exemple #6
0
def bind_toy():
    """
    :return:
    """
    user_list = []
    device_key = request.form.get("device_key")
    user_id = request.form.get("user_id")
    toy_name = request.form.get("toy_name")
    baby_name = request.form.get("baby_name")
    remark = request.form.get("remark")
    gender = request.form.get("gender")

    # 1.创建玩具的基本信息
    chat_id = MONGO_DB.chat.insert_one({})  # 没主儿的chat

    user_info = MONGO_DB.users.find_one({"_id": ObjectId(user_id)})  # 查询用户基本信息
    user_list.append(str(user_info.get("_id")))

    # 2.绑定用户与玩具关系
    toy_info = {
        "device_key": device_key,
        "bind_user": user_id,
        "toy_name": toy_name,
        "avatar": "toy.jpg",
        "baby_name": baby_name,
        "gender": gender,
        "friend_list": []
    }
    # 3.成为玩具的第一个好友
    frist_friend = {
        "friend_nickname": user_info.get("nickname"),  # 徐中一不不知道前不强
        "friend_avatar": user_info.get("avatar"),
        "friend_remark": remark,  # 强强
        "friend_chat": str(chat_id.inserted_id)
    }

    toy_info["friend_list"].append(frist_friend)

    toy_id = MONGO_DB.toys.insert_one(toy_info)

    user_list.append(toy_id.inserted_id)

    MONGO_DB.chat.update_one(
        {"_id": chat_id.inserted_id},
        {"$set": {"user_list": user_list, "chat_list": []}}
    )

    user_info["bind_toys"].append(str(toy_id.inserted_id))
    user_info["friend_list"].append(
        {
            "friend_nickname": toy_info.get("baby_name"),
            "friend_avatar": toy_info.get("avatar"),
            "friend_remark": toy_info.get("baby_name"),
            "friend_chat": str(chat_id.inserted_id)
        }
    )

    MONGO_DB.users.update_one({"_id": ObjectId(user_id)}, {"$set": user_info})

    RET["code"] = 0
    RET["msg"] = "绑定成功"
    RET["data"] = {}

    return jsonify(RET)
 def test_get_landmark_from_api(self):
     tour_id = ObjectId('5eeb86c96d5f80c5f2fdbb00')
     result = self.app.get(f'/api/v1/tours/{tour_id}/tourview')
     self.assertIsNotNone(result)
print('Getting all resources older than {:%Y-%m-%d %H:%M}...'.format(time))

rsrcs = db.clarin.resources.find({'modified': {'$lt': time}})

ids = set()
for res in rsrcs:
    ids.add(res['_id'])

print('Discarding anything that can be used in EMU projects...')

projs = db.clarin.emu.find({})
for proj in projs:
    for name, bndl in proj['bundles'].items():
        if 'audio' in bndl:
            ids.discard(ObjectId(bndl['audio']))
        if 'trans' in bndl:
            ids.discard(ObjectId(bndl['trans']))
        if 'seg' in bndl:
            ids.discard(ObjectId(bndl['seg']))

print(f'Deleting {len(ids)} resources...')

for id in ids:
    db.clarin.resources.remove({'_id': id})

print('Making a list of files in databse...')

rsrcs = db.clarin.resources.find({})

db_files = set()
Exemple #9
0
 def get(id, step_id):
     return mongo.db.projects.find_one(
         {
             '_id': ObjectId(id),
             'steps._id': ObjectId(step_id)
         }, {'steps.$': 1})
    def testgetResult(self):
        urls = [
            {
                "_id": 1,
                "r_id": ObjectId('4e4c7b9f5bc89412ec000004'),
                "url": "http://www.chinacache.com/a.jpg",
                "status": "PROGRESS",
                "isdir": False,
                "finish_time": '20110624142700',
                "action": "purge",
                "is_multilayer": False,
                "channel_code": "0005",
                "created_time": ""
            },
            {
                "_id": 2,
                "r_id": ObjectId('4e4c7b9f5bc89412ec000004'),
                "url": "http://www.chinacache.com/u.jpg",
                "status": "PROGRESS",
                "isdir": False,
                "finish_time": '20110624142700',
                "action": "expire",
                "is_multilayer": False,
                "channel_code": "0005",
                "created_time": ""
            },
        ]
        result = mock()

        when(self.db_session.request).find({
            "username": '******',
            "created_time": {
                "$gte": datetime.strptime('20110624142500', '%Y%m%d%H%M%S'),
                "$lte": datetime.strptime('20110624142800', '%Y%m%d%H%M%S')
            }
        }).thenReturn(result)
        when(result).limit(1000).thenReturn([{
            'created_time':
            '2012-01-01 01:01:01',
            'remote_addr':
            '0.0.0.1',
            'serial_num':
            '123456',
            '_id':
            ObjectId('4e4c7b9f5bc89412ec000004')
        }])
        when(self.db_session.url).find({
            'r_id':
            ObjectId('4e4c7b9f5bc89412ec000004')
        }).thenReturn(urls)
        when(result_tencent).getStatus({
            "_id":
            1,
            "r_id":
            ObjectId('4e4c7b9f5bc89412ec000004'),
            "url":
            "http://www.chinacache.com/a.jpg",
            "status":
            "PROGRESS",
            "isdir":
            False,
            "finish_time":
            '20110624142700',
            "action":
            "purge",
            "is_multilayer":
            False,
            "channel_code":
            "0005",
            "created_time":
            ""
        }).thenReturn(0)
        when(result_tencent).getStatus({
            "_id":
            2,
            "r_id":
            ObjectId('4e4c7b9f5bc89412ec000004'),
            "url":
            "http://www.chinacache.com/u.jpg",
            "status":
            "PROGRESS",
            "isdir":
            False,
            "finish_time":
            '20110624142700',
            "action":
            "expire",
            "is_multilayer":
            False,
            "channel_code":
            "0005",
            "created_time":
            ""
        }).thenReturn(0)
        result_str = u'{"ret":"0","msg":"下列是URL 更新状态列表"}\n2012-01-01 01:01:01\t123456\t0.0.0.1\thttp://www.chinacache.com/a.jpg\t20110624142700\t0\t完成\n2012-01-01 01:01:01\t123456\t0.0.0.1\thttp://www.chinacache.com/u.jpg\t20110624142700\t0\t完成\n'
        self.assertEquals(
            result_tencent.get_result(self.db_session, '20110624142500',
                                      '20110624142800', 'test'), result_str)
Exemple #11
0
# projectionFields = {'_id':False}  # 用字典指定
# queryArgs = {"total_zone_name":"pudong"}
#
# searcher = db_coll.find({})
#
# while True:
#     try:
#         dict = searcher.next()
#         print(len(dict))
#     except StopIteration:
#         break

bulid_time = time.strftime('%m/%d/%Y %H:%M:%S', time.localtime())
base_date = {'bulid_time': bulid_time}
db_coll.insert(base_date)
l = len(db_coll.find(base_date).next())
print(l)
id = db_coll.find(base_date).next()['_id']

from bson import ObjectId

for i in range(100):
    l = len(db_coll.find({'_id': ObjectId(id)}).next())
    if l < 10:
        db_coll.update({'_id': ObjectId(id)}, {'$set': {str(i): i}})
    else:
        bulid_time = time.strftime('%m/%d/%Y %H:%M:%S', time.localtime())
        base_date = {'bulid_time': bulid_time}
        db_coll.insert(base_date)
        id = db_coll.find(base_date).next()['_id']
Exemple #12
0
def delete_by_id(id: str) -> TrainingJob:
    document: dict = _collection.find_one_and_delete(
        filter={'_id': ObjectId(id)})
    return TrainingJob(**document)
Exemple #13
0
def exists_by_id(id: str) -> bool:
    count = _collection.count_documents(filter={'_id': ObjectId(id)}, limit=1)
    return bool(count)
Exemple #14
0
def getNaturopathyByVendor(self):
    code = 200
    status = False
    message = ""
    responseData = {}
    serData = []
    where = {}

    if request.args.get("vendor_id") and request.args.get("vendor_id") != "":
        where["vendor_id"] = ObjectId(request.args.get("vendor_id"))
        where["is_delete"] = 0
        where["status"] = 1
        if request.args.get("outlet_id"):
            where["outlet_id"] = ObjectId(request.args.get("outlet_id"))
        serData = DB.find_by_key(tbl_v028_meditation_naturopathy, where)

        if serData:

            getCat = DB.find_all(tbl_v006_service_category, {
                "category_name": 1,
                "_id": 1
            })

            catData = {}
            if getCat:
                for c in getCat:
                    if "category_name" in c and c["category_name"] != "":
                        catData[c["_id"]["$oid"]] = c["category_name"]

            getOut = DB.find_all(tbl_v004_outlets, {"name": 1, "_id": 1})
            outData = {}
            if getOut:
                for c in getOut:
                    outData[c["_id"]["$oid"]] = c["name"]

            resData = []
            for x in serData:
                x["_id"] = str(x["_id"]["$oid"])

                if "$oid" in x["user_id"]:
                    x["user_id"] = str(x["user_id"]["$oid"])
                x["vendor_id"] = str(x["vendor_id"]["$oid"])
                x["outlet_id"] = str(x["outlet_id"]["$oid"])

                if "service_master_id" in x:
                    if isinstance(x["service_master_id"], list):
                        for sm in range(len(x["service_master_id"])):
                            x["service_master_id"][
                                sm] = x["service_master_id"][sm][
                                    "$oid"] if "$oid" in x["service_master_id"][
                                        sm] else x["service_master_id"][sm]
                    else:
                        x["service_master_id"] = [
                            x["service_master_id"]["$oid"]
                            if "$oid" in x["service_master_id"] else
                            x["service_master_id"]
                        ]

                if x["outlet_id"] in outData:
                    x["outlet_name"] = outData[x["outlet_id"]]
                catId = []
                if isinstance(x["category_id"], list):
                    for ci in range(len(x["category_id"])):
                        x["category_id"][ci] = x["category_id"][ci]["$oid"]
                        if x["category_id"][ci] in catData:
                            catId.append({
                                "category_id":
                                x["category_id"][ci],
                                "name":
                                catData[x["category_id"][ci]].title()
                            })

                    x["category_id"] = catId
                else:
                    x["category_id"] = x["category_id"]["$oid"] if "$oid" in x[
                        "category_id"] else ""
                    if x["category_id"] in catData:
                        x["category_id"] = [{
                            "category_id":
                            x["category_id"],
                            "name":
                            catData[x["category_id"]].title()
                        }]
                resData.append(x)
            responseData = list(reversed(resData))
            code = 200
            status = True
            message = MSG_CONST.VENDOR_SERVICES_SUCCESS
        else:
            code = 201
            status = False
            message = MSG_CONST.VENDOR_OUTLET_NOT_FOUND
    else:
        code = 201
        status = False
        message = MSG_CONST.VENDOR_EMPTY_ID
    response = output_json(responseData, message, status, code)
    logging.debug('vendor_services_list: {}'.format(response))
    return response
Exemple #15
0
 def test_api_onplat(self):
     mdl = RootUserModel(OnPlatOids=[ObjectId()], ApiOid=ObjectId())
     self.assertTrue(mdl.has_api_data)
     self.assertTrue(mdl.has_onplat_data)
Exemple #16
0
 def get(id):
     return mongo.db.projects.find_one({'_id': ObjectId(id)})
Exemple #17
0
def get_url(uid):
    obj_url = query_db_session.url.find_one({"_id": ObjectId(uid)})
    if obj_url:
        return obj_url
    else:
        return None
def listFailedPosts(user, page = 0, page_size = 100000) :
	uid = ObjectId(user['_id'])
	result = tagdb.db.failed_posts.find({'uid': uid})
	result = result.skip(page * page_size).limit(page_size)
	return result, result.count()
 def test_cannot_get_inexistent_tour(self):
     # We need create a random a value
     empty = ObjectId("000000000000000000000000")
     result = self.app.get(f'/api/v1/tours/{empty}')
     self.assertTrue(result.status_code == 404)
 def validate(cls, v):
     if not ObjectId.is_valid(v):
         raise ValueError('Invalid objectid')
     return ObjectId(v)
 def test_cannot_get_inexistent_landmark_from_api(self):
     empty = ObjectId('000000000000000000000000')
     result = self.app.get(f'/api/v1/tours/{empty}/tourview')
     self.assertTrue(result.status_code == 404)
Exemple #22
0
def edit_role():

    rid = request.argget.all('id').strip()
    name = request.argget.all('name').strip()
    instructions = request.argget.all('instructions').strip()
    default = int(request.argget.all('default', 0))
    temp_permissions = json_to_pyseq(request.argget.all('permissions', []))

    permissions = 0x0
    for i in temp_permissions:
        permissions = permissions | int(i)

    s, r = arg_verify(reqargs=[(gettext("name"), name)], required=True)
    if not s:
        return r

    data = {
        "msg":
        gettext(
            "The current user permissions are lower than the permissions you want to modify,"
            " without permission to modify"),
        "msg_type":
        "w",
        "custom_status":
        401
    }
    user_role = mdbs["user"].db.role.find_one(
        {"_id": ObjectId(current_user.role_id)})
    # 如果当前用户的权限最高位 小于 要修改成的这个角色权重的最高位,是不可以的
    if get_num_digits(user_role["permissions"]) < get_num_digits(permissions):
        return data
    elif get_num_digits(
            user_role["permissions"]) == get_num_digits(permissions):
        role = {
            "name": name,
            "instructions": instructions,
        }
        r = mdbs["user"].db.role.update_one({"_id": ObjectId(rid)},
                                            {"$set": role})
        if not r.modified_count:
            data = {
                'msg': gettext("No changes"),
                'msg_type': "w",
                "custom_status": 201
            }
        else:
            data = {
                "msg":
                gettext(
                    "The highest permission of the current user is equal to that of the selected permission."
                    " You can only modify the name and profile."),
                "msg_type":
                "s",
                "custom_status":
                201
            }
        return data

    old_role = mdbs["user"].db.role.find_one({"_id": ObjectId(rid)})
    # 如果当前用户的权限最高位 小于 要修改角色的权限,也是不可以
    if old_role and get_num_digits(old_role["permissions"]) >= get_num_digits(
            user_role["permissions"]):
        return data

    elif old_role and get_num_digits(
            old_role["permissions"]) == get_num_digits(
                user_role["permissions"]):
        role = {
            "name": name,
            "instructions": instructions,
        }
        r = mdbs["user"].db.role.update_one({"_id": ObjectId(rid)},
                                            {"$set": role})
        if not r.modified_count:
            data = {
                'msg': gettext("No changes"),
                'msg_type': "w",
                "custom_status": 201
            }
        else:
            data = {
                "msg":
                gettext(
                    "The highest permission of the current user is equal to that of the role to be modified."
                    "Only the name and introduction can be modified."),
                "msg_type":
                "s",
                "custom_status":
                201
            }
        return data

    else:
        role = {
            "name": name,
            "instructions": instructions,
            'permissions': permissions,
            "default": default
        }

    data = {
        'msg': gettext("Save success"),
        'msg_type': "s",
        "custom_status": 201
    }
    if not mdbs["user"].db.role.find_one({
            "name": name,
            "_id": {
                "$ne": ObjectId(rid)
            }
    }):
        if default:
            if not mdbs["user"].db.role.find_one({
                    "default": {
                        "$in": [1, True]
                    },
                    "_id": {
                        "$ne": ObjectId(rid)
                    }
            }):
                r = mdbs["user"].db.role.update_one({"_id": ObjectId(rid)},
                                                    {"$set": role})
                if not r.modified_count:
                    data = {
                        'msg': gettext("No changes"),
                        'msg_type': "w",
                        "custom_status": 201
                    }
            else:
                data = {
                    'msg': gettext("Existing default role"),
                    'msg_type': "w",
                    "custom_status": 403
                }
        else:
            r = mdbs["user"].db.role.update_one({"_id": ObjectId(rid)},
                                                {"$set": role})
            if not r.modified_count:
                data = {
                    'msg': gettext("No changes"),
                    'msg_type': "w",
                    "custom_status": 201
                }

    else:
        data = {
            'msg': gettext("Role name already exists"),
            'msg_type': "w",
            "custom_status": 403
        }

    return data
Exemple #23
0
def post_edit(post_id):

    view_data = {
        'title': u'编辑-{}'.format(config['title'].TITLE),
        'hint': '正在编辑'
    }
    view_data['permission'] = Permission.ECP
    view_data['help'] = mdb_cont.db.posts.find_one({
        'type': u'帮助',
        'title': u'文章编辑帮助'
    })
    post = mdb_cont.db.posts.find_one_or_404({
        '_id': ObjectId(post_id),
        'user_id': current_user.id
    })
    if post['subject'] == "tech":
        view_data['hint'] = '科技有趣'
    elif post['subject'] == "art":
        view_data['hint'] = '音乐|艺术'
    elif post['subject'] == "sys":
        if not current_user.is_role(Permission.ECP):
            abort(404)
        view_data['hint'] = '系统告示'

    form = EditPost(post['subject'])
    if form.issue.data:
        # if current_user.can(Permission.ECP):
        #     status = 1
        # else:
        #     status = 2
        status = 1
        tag_list = request.form.getlist("boolean_l")
        # 封面图片
        img_url = post_img(form.body.data, form.s_type.data)
        if current_user.can(Permission.ECP):
            form.body.data = sys_edit_img_log_claer(
                form.body.data, post_title=form.title.data.strip())
        else:
            form.body.data = edit_img_log_claer(form.body.data, post_id)
        # tag
        if post['is_been']:
            _time = post['time']
            _is_been = post['is_been']
        else:
            _time = time.time()
            _is_been = 1
        post = {
            'title': form.title.data.strip(),
            'body': form.body.data,
            'status': status,
            'type': form.s_type.data,
            'img_url': img_url,
            'time': _time,
            'is_been': _is_been,
            'update_time': time.time(),
        }
        if tag_list:
            post['tag'] = tag_list

        mdb_cont.db.posts.update(
            {
                '_id': ObjectId(post_id),
                'user_id': current_user.id
            }, {'$set': post})
        if status == 1:
            post_cnt_update(current_user.id)
            flash({
                'msg':
                u'更新成功!首页|专栏可能延迟{}秒更新.'.format(config['cache_timeout'].POSTS),
                "type":
                's'
            })
            return redirect(url_for('post.show', post_id=post_id))
        else:
            return redirect(url_for('post.preview', post_id=post_id))

    elif form.draft.data:
        status = 0
        tag_list = request.form.getlist("boolean_l")
        # 图片
        img_url = post_img(form.body.data, form.s_type.data)
        form.body.data = edit_img_log_claer(form.body.data, post_id)

        post = {
            'title': form.title.data.strip(),
            'body': form.body.data,
            'type': form.s_type.data,
            'img_url': img_url,
            'status': status,
            'update_time': time.time()
        }
        if tag_list:
            post['tag'] = tag_list
        post_cnt_update(current_user.id)
        mdb_cont.db.posts.update(
            {
                '_id': ObjectId(post_id),
                'user_id': current_user.id
            }, {'$set': post})
        return redirect(url_for('post.preview', post_id=post_id))

    # view_data

    view_data['tag_s'] = []
    tags = mdb_cont.db.tag.find_one({'user_id': 0})
    if tags:
        view_data['tag_s'] = tags['tag']

    view_data['tag_u'] = []
    tags = mdb_cont.db.tag.find_one({'user_id': current_user.id})
    if tags:
        view_data['tag_u'] = tags['tag']

    #post

    form.title.data = post['title']
    form.body.data = post['body']
    form.s_type.data = post['type']
    view_data['edit'] = True
    view_data['post'] = post
    # 记录图片url
    post_img_statis(post['body'], post['_id'])

    return render_template('post/posts/edit.html',
                           form=form,
                           view_data=view_data)
Exemple #24
0
def add_role():

    name = request.argget.all('name').strip()
    instructions = request.argget.all('instructions').strip()
    default = int(request.argget.all('default', False).strip())
    temp_permissions = json_to_pyseq(request.argget.all('permissions', []))
    data = {
        'msg': gettext("Add a success"),
        'msg_type': "s",
        "custom_status": 201
    }

    permissions = 0x0
    for i in temp_permissions:
        permissions = permissions | int(i)

    s, r = arg_verify(reqargs=[(gettext("name"), name)], required=True)
    if not s:
        return r
    elif not mdbs["user"].db.role.find_one({gettext("name"): name}):

        # 权限检查
        user_role = mdbs["user"].db.role.find_one(
            {"_id": ObjectId(current_user.role_id)})
        if get_num_digits(
                user_role["permissions"]) <= get_num_digits(permissions):
            data = {
                "msg":
                gettext(
                    "The current user permissions are lower than the permissions that you want to add,"
                    " without permission to add"),
                "msg_type":
                "w",
                "custom_status":
                401
            }
            return data

        if default:
            if not mdbs["user"].db.role.find_one(
                {"default": {
                    "$in": [1, True]
                }}):
                mdbs["user"].db.role.insert_one({
                    "name": name,
                    "instructions": instructions,
                    'permissions': permissions,
                    "default": default
                })
            else:
                data = {
                    'msg': gettext("Existing default role"),
                    'msg_type': "w",
                    "custom_status": 403
                }
        else:
            mdbs["user"].db.role.insert_one({
                "name": name,
                "instructions": instructions,
                'permissions': permissions,
                "default": default
            })

    else:
        data = {
            'msg': gettext("Role name already exists"),
            'msg_type': "w",
            "custom_status": 403
        }

    return data
Exemple #25
0
def remove(restaurant):
    return db_clustering_map.restaurants.delete_one(
        {"_id": ObjectId(restaurant)})
Exemple #26
0
 def test_api_only(self):
     mdl = RootUserModel(ApiOid=ObjectId())
     self.assertTrue(mdl.has_api_data)
     self.assertFalse(mdl.has_onplat_data)
 def buscar_prova(self, id_prova: int):
     return self.provas.find({'_id': ObjectId(id_prova)})
Exemple #28
0
 def test_onplat_only(self):
     mdl = RootUserModel(OnPlatOids=[ObjectId()])
     self.assertFalse(mdl.has_api_data)
     self.assertTrue(mdl.has_onplat_data)
Exemple #29
0
 def delete(self, index, id):
     self.cols[index].delete_one({'_id': ObjectId(id)})
class Mongo(DataLayer):
    """ MongoDB data access layer for Eve REST API.

    .. versionchanged:: 0.5
       Properly serialize nullable float and integers. #469.
       Return 400 if unsupported query operators are used. #387.

    .. versionchanged:: 0.4
       Don't serialize to objectid if value is null. #341.

    .. versionchanged:: 0.2
       Provide the specialized json serializer class as ``json_encoder_class``.

    .. versionchanged:: 0.1.1
       'serializers' added.
    """

    serializers = {
        "objectid": lambda value: ObjectId(value) if value else None,
        "datetime": str_to_date,
        "integer": lambda value: int(value) if value is not None else None,
        "float": lambda value: float(value) if value is not None else None,
        "number": lambda val: json.loads(val) if val is not None else None,
        "boolean": lambda v: {"1": True, "true": True, "0": False, "false": False}[
            str(v).lower()
        ],
        "dbref": lambda value: DBRef(
            value["$col"] if "$col" in value else value["$ref"],
            value["$id"],
            value["$db"] if "$db" in value else None,
        )
        if value is not None
        else None,
        "decimal": lambda value: decimal128.Decimal128(decimal.Decimal(str(value)))
        if value is not None
        else None,
    }

    # JSON serializer is a class attribute. Allows extensions to replace it
    # with their own implementation.
    json_encoder_class = MongoJSONEncoder

    operators = set(
        ["$gt", "$gte", "$in", "$lt", "$lte", "$ne", "$nin", "$eq"]
        + ["$or", "$and", "$not", "$nor"]
        + ["$mod", "$regex", "$text", "$where"]
        + ["$options", "$search", "$language", "$caseSensitive"]
        + ["$diacriticSensitive", "$exists", "$type"]
        + ["$geoWithin", "$geoIntersects", "$near", "$nearSphere", "$centerSphere"]
        + ["$geometry", "$maxDistance", "$minDistance", "$box"]
        + ["$all", "$elemMatch", "$size"]
        + ["$bitsAllClear", "$bitsAllSet", "$bitsAnyClear", "$bitsAnySet"]
        + ["$center", "$expr"]
    )

    def init_app(self, app):
        """ Initialize PyMongo.

        .. versionchanged:: 0.6
           Use mongo_prefix for multidb support.

        .. versionchanged:: 0.0.9
           Support for Python 3.3.
        """
        # mongod must be running or this will raise an exception
        self.driver = PyMongos(self)
        self.mongo_prefix = None

    def find(self, resource, req, sub_resource_lookup, perform_count=True):
        """ Retrieves a set of documents matching a given request. Queries can
        be expressed in two different formats: the mongo query syntax, and the
        python syntax. The first kind of query would look like: ::

            ?where={"name": "john doe"}

        while the second would look like: ::

            ?where=name=="john doe"

        The resultset if paginated.

        :param resource: resource name.
        :param req: a :class:`ParsedRequest`instance.
        :param sub_resource_lookup: sub-resource lookup from the endpoint url.

        .. versionchanged:: 0.6
           Support for multiple databases.
           Filter soft deleted documents by default

        .. versionchanged:: 0.5
           Support for comma delimited sort syntax. Addresses #443.
           Return the error if a blacklisted MongoDB operator is used in query.
           Abort with 400 if unsupported query operator is used. #387.
           Abort with 400 in case of invalid sort syntax. #387.

        .. versionchanged:: 0.4
           'allowed_filters' is now checked before adding 'sub_resource_lookup'
           to the query, as it is considered safe.
           Refactored to use self._client_projection since projection is now
           honored by getitem() as well.

        .. versionchanged:: 0.3
           Support for new _mongotize() signature.

        .. versionchanged:: 0.2
           Support for sub-resources.
           Support for 'default_sort'.

        .. versionchanged:: 0.1.1
           Better query handling. We're now properly casting objectid-like
           strings to ObjectIds. Also, we're casting both datetimes and
           objectids even when the query was originally in python syntax.

        .. versionchanged:: 0.0.9
           More informative error messages.

        .. versionchanged:: 0.0.7
           Abort with a 400 if the query includes blacklisted  operators.

        .. versionchanged:: 0.0.6
           Only retrieve fields in the resource schema
           Support for projection queries ('?projection={"name": 1}')

        .. versionchanged:: 0.0.5
           handles the case where req.max_results is None because pagination
           has been disabled.

        .. versionchanged:: 0.0.4
           retrieves the target collection via the new config.SOURCES helper.
        """
        args = dict()

        if req and req.max_results:
            args["limit"] = req.max_results

        if req and req.page > 1:
            args["skip"] = (req.page - 1) * req.max_results

        # TODO sort syntax should probably be coherent with 'where': either
        # mongo-like # or python-like. Currently accepts only mongo-like sort
        # syntax.

        # TODO should validate on unknown sort fields (mongo driver doesn't
        # return an error)

        client_sort = self._convert_sort_request_to_dict(req)
        spec = self._convert_where_request_to_dict(resource, req)

        bad_filter = validate_filters(spec, resource)
        if bad_filter:
            abort(400, bad_filter)

        if sub_resource_lookup:
            spec = self.combine_queries(spec, sub_resource_lookup)

        if (
            config.DOMAIN[resource]["soft_delete"]
            and not (req and req.show_deleted)
            and not self.query_contains_field(spec, config.DELETED)
        ):
            # Soft delete filtering applied after validate_filters call as
            # querying against the DELETED field must always be allowed when
            # soft_delete is enabled
            spec = self.combine_queries(spec, {config.DELETED: {"$ne": True}})

        spec = self._mongotize(spec, resource)

        client_projection = self._client_projection(req)

        datasource, spec, projection, sort = self._datasource_ex(
            resource, spec, client_projection, client_sort
        )

        if req and req.if_modified_since:
            spec[config.LAST_UPDATED] = {"$gt": req.if_modified_since}

        if len(spec) > 0:
            args["filter"] = spec

        if sort is not None:
            args["sort"] = sort

        if projection:
            args["projection"] = projection

        target = self.pymongo(resource).db[datasource]
        try:
            result = target.find(**args)
        except TypeError as e:
            # pymongo raises ValueError when invalid query paramenters are
            # included. We do our best to catch them beforehand but, especially
            # with key/value sort syntax, invalid ones might still slip in.
            self.app.logger.exception(e)
            abort(400, description=debug_error_message(str(e)))

        if perform_count:
            try:
                count = target.count_documents(spec)
            except:
                # fallback to deprecated method. this might happen when the query
                # includes operators not supported by count_documents(). one
                # documented use-case is when we're running on mongo 3.4 and below,
                # which does not support $expr ($expr must replace $where # in
                # count_documents()).

                # 1. Mongo 3.6+; $expr: pass
                # 2. Mongo 3.6+; $where: pass (via fallback)
                # 3. Mongo 3.4; $where: pass (via fallback)
                # 4. Mongo 3.4; $expr: fail (operator not supported by db)

                # See: http://api.mongodb.com/python/current/api/pymongo/collection.html#pymongo.collection.Collection.count
                count = target.count()
        else:
            count = None

        return result, count

    def find_one(
        self,
        resource,
        req,
        check_auth_value=True,
        force_auth_field_projection=False,
        **lookup
    ):
        """ Retrieves a single document.

        :param resource: resource name.
        :param req: a :class:`ParsedRequest` instance.
        :param **lookup: lookup query.

        .. versionchanged:: 0.6
           Support for multiple databases.
           Filter soft deleted documents by default

        .. versionchanged:: 0.4
           Honor client projection requests.

        .. versionchanged:: 0.3.0
           Support for new _mongotize() signature.
           Custom ID_FIELD lookups would raise an exception. See #203.

        .. versionchanged:: 0.1.0
           ID_FIELD to ObjectID conversion is done before `_datasource_ex` is
           called.

        .. versionchanged:: 0.0.6
           Only retrieve fields in the resource schema

        .. versionchanged:: 0.0.4
           retrieves the target collection via the new config.SOURCES helper.
        """
        self._mongotize(lookup, resource)

        client_projection = self._client_projection(req)

        datasource, filter_, projection, _ = self._datasource_ex(
            resource,
            lookup,
            client_projection,
            check_auth_value=check_auth_value,
            force_auth_field_projection=force_auth_field_projection,
        )

        if (
            (config.DOMAIN[resource]["soft_delete"])
            and (not req or not req.show_deleted)
            and (not self.query_contains_field(lookup, config.DELETED))
        ):
            filter_ = self.combine_queries(filter_, {config.DELETED: {"$ne": True}})
        # Here, we feed pymongo with `None` if projection is empty.
        return (
            self.pymongo(resource).db[datasource].find_one(filter_, projection or None)
        )

    def find_one_raw(self, resource, **lookup):
        """ Retrieves a single raw document.

        :param resource: resource name.
        :param **lookup: lookup query.

        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionadded:: 0.4
        """
        id_field = config.DOMAIN[resource]["id_field"]
        _id = lookup.get(id_field)
        datasource, filter_, _, _ = self._datasource_ex(resource, {id_field: _id}, None)

        lookup = self._mongotize(lookup, resource)

        return self.pymongo(resource).db[datasource].find_one(lookup)

    def find_list_of_ids(self, resource, ids, client_projection=None):
        """ Retrieves a list of documents from the collection given
        by `resource`, matching the given list of ids.

        This query is generated to *preserve the order* of the elements
        in the `ids` list. An alternative would be to use the `$in` operator
        and accept non-dependable ordering for a slight performance boost
        see <https://jira.mongodb.org/browse/SERVER-7528?focusedCommentId=
        181518&page=com.atlassian.jira.plugin.system.issuetabpanels:comment
        -tabpanel#comment-181518>

        To preserve order, we use a query of the form
            db.collection.find( { $or:[ { _id:ObjectId(...) },
                { _id:ObjectId(...) }...] } )

        Instead of the simpler
            {'_id': {'$in': ids}}

        -- via http://stackoverflow.com/a/13185509/1161906

        :param resource: resource name.
        :param ids: a list of ObjectIds corresponding to the documents
        to retrieve
        :param client_projection: a specific projection to use
        :return: a list of documents matching the ids in `ids` from the
        collection specified in `resource`

        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionchanged:: 0.1.1
           Using config.ID_FIELD instead of hard coded '_id'.

        .. versionadded:: 0.1.0
        """
        id_field = config.DOMAIN[resource]["id_field"]
        query = {"$or": [{id_field: id_} for id_ in ids]}

        datasource, spec, projection, _ = self._datasource_ex(
            resource, query=query, client_projection=client_projection
        )
        # projection of {} return all fields in MongoDB, but
        # pymongo will only return `_id`. It's a design flaw upstream.
        # Here, we feed pymongo with `None` if projection is empty.
        documents = (
            self.pymongo(resource)
            .db[datasource]
            .find(filter=spec, projection=(projection or None))
        )
        return documents

    def aggregate(self, resource, pipeline, options):
        """
        .. versionadded:: 0.7
        """
        datasource, _, _, _ = self.datasource(resource)
        challenge = self._mongotize({"key": pipeline}, resource)["key"]

        return self.pymongo(resource).db[datasource].aggregate(challenge, **options)

    def insert(self, resource, doc_or_docs):
        """ Inserts a document into a resource collection.

        .. versionchanged:: 0.6.1
           Support for PyMongo 3.0.

        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionchanged:: 0.0.9
           More informative error messages.

        .. versionchanged:: 0.0.8
           'write_concern' support.

        .. versionchanged:: 0.0.6
           projection queries ('?projection={"name": 1}')
           'document' param renamed to 'doc_or_docs', making support for bulk
           inserts apparent.

        .. versionchanged:: 0.0.4
           retrieves the target collection via the new config.SOURCES helper.
        """
        datasource, _, _, _ = self._datasource_ex(resource)

        coll = self.get_collection_with_write_concern(datasource, resource)

        if isinstance(doc_or_docs, dict):
            doc_or_docs = [doc_or_docs]

        try:
            return coll.insert_many(doc_or_docs, ordered=True).inserted_ids
        except pymongo.errors.BulkWriteError as e:
            self.app.logger.exception(e)

            # since this is an ordered bulk operation, all remaining inserts
            # are aborted. Be aware that if BULK_ENABLED is True and more than
            # one document is included with the payload, some documents might
            # have been successfully inserted, even if the operation was
            # aborted.

            # report a duplicate key error since this can probably be
            # handled by the client.
            for error in e.details["writeErrors"]:
                # amazingly enough, pymongo does not appear to be exposing
                # error codes as constants.
                if error["code"] == 11000:
                    abort(
                        409,
                        description=debug_error_message(
                            "Duplicate key error at index: %s, message: %s"
                            % (error["index"], error["errmsg"])
                        ),
                    )

            abort(
                500,
                description=debug_error_message(
                    "pymongo.errors.BulkWriteError: %s" % e
                ),
            )

    def _change_request(self, resource, id_, changes, original, replace=False):
        """ Performs a change, be it a replace or update.

        .. versionchanged:: 0.8.2
           Return 400 if update/replace with malformed DBRef field. See #1257.

        .. versionchanged:: 0.6.1
           Support for PyMongo 3.0.

        .. versionchanged:: 0.6
           Return 400 if an attempt is made to update/replace an immutable
           field.
        """
        id_field = config.DOMAIN[resource]["id_field"]
        query = {id_field: id_}
        if config.ETAG in original:
            query[config.ETAG] = original[config.ETAG]

        datasource, filter_, _, _ = self._datasource_ex(resource, query)

        coll = self.get_collection_with_write_concern(datasource, resource)
        try:
            result = (
                coll.replace_one(filter_, changes)
                if replace
                else coll.update_one(filter_, changes)
            )
            if (
                config.ETAG in original
                and result
                and result.acknowledged
                and result.modified_count == 0
            ):
                raise self.OriginalChangedError()
        except pymongo.errors.DuplicateKeyError as e:
            abort(
                400,
                description=debug_error_message(
                    "pymongo.errors.DuplicateKeyError: %s" % e
                ),
            )
        except (pymongo.errors.WriteError, pymongo.errors.OperationFailure) as e:
            # server error codes and messages changed between 2.4 and 2.6/3.0.
            server_version = self.driver.db.client.server_info()["version"][:3]
            if (server_version == "2.4" and e.code in (13596, 10148)) or e.code in (
                66,
                16837,
            ):
                # attempt to update an immutable field. this usually
                # happens when a PATCH or PUT includes a mismatching ID_FIELD.
                self.app.logger.warning(e)
                description = (
                    debug_error_message("pymongo.errors.OperationFailure: %s" % e)
                    or "Attempt to update an immutable field. Usually happens "
                    "when PATCH or PUT include a '%s' field, "
                    "which is immutable (PUT can include it as long as "
                    "it is unchanged)." % id_field
                )

                abort(400, description=description)
            else:
                # see comment in :func:`insert()`.
                self.app.logger.exception(e)
                abort(
                    500,
                    description=debug_error_message(
                        "pymongo.errors.OperationFailure: %s" % e
                    ),
                )

    def update(self, resource, id_, updates, original):
        """ Updates a collection document.
        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionchanged:: 5.2
           Raise OriginalChangedError if document is changed from the
           specified original.

        .. versionchanged:: 0.4
           Return a 400 on pymongo DuplicateKeyError.

        .. versionchanged:: 0.3.0
           Custom ID_FIELD lookups would fail. See #203.

        .. versionchanged:: 0.2
           Don't explicitly convert ID_FIELD to ObjectId anymore, so we can
           also process different types (UUIDs etc).

        .. versionchanged:: 0.0.9
           More informative error messages.

        .. versionchanged:: 0.0.8
           'write_concern' support.

        .. versionchanged:: 0.0.6
           projection queries ('?projection={"name": 1}')

        .. versionchanged:: 0.0.4
           retrieves the target collection via the new config.SOURCES helper.
        """

        return self._change_request(resource, id_, {"$set": updates}, original)

    def replace(self, resource, id_, document, original):
        """ Replaces an existing document.
        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionchanged:: 5.2
           Raise OriginalChangedError if document is changed from the
           specified original.

        .. versionchanged:: 0.3.0
           Custom ID_FIELD lookups would fail. See #203.

        .. versionchanged:: 0.2
           Don't explicitly convert ID_FIELD to ObjectId anymore, so we can
           also process different types (UUIDs etc).

        .. versionadded:: 0.1.0
        """

        return self._change_request(resource, id_, document, original, replace=True)

    def remove(self, resource, lookup):
        """ Removes a document or the entire set of documents from a
        collection.

        .. versionchanged:: 0.6.1
           Support for PyMongo 3.0.

        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionchanged:: 0.3
           Support lookup arg, which allows to properly delete sub-resources
           (only delete documents that meet a certain constraint).

        .. versionchanged:: 0.2
           Don't explicitly converto ID_FIELD to ObjectId anymore, so we can
           also process different types (UUIDs etc).

        .. versionchanged:: 0.0.9
           More informative error messages.

        .. versionchanged:: 0.0.8
           'write_concern' support.

        .. versionchanged:: 0.0.6
           projection queries ('?projection={"name": 1}')

        .. versionchanged:: 0.0.4
           retrieves the target collection via the new config.SOURCES helper.

        .. versionadded:: 0.0.2
            Support for deletion of entire documents collection.
        :returns
            A document (dict) describing the effect of the remove
            or None if write acknowledgement is disabled.
        """
        lookup = self._mongotize(lookup, resource)
        datasource, filter_, _, _ = self._datasource_ex(resource, lookup)

        coll = self.get_collection_with_write_concern(datasource, resource)
        try:
            coll.delete_many(filter_)
        except pymongo.errors.OperationFailure as e:
            # see comment in :func:`insert()`.
            self.app.logger.exception(e)
            abort(
                500,
                description=debug_error_message(
                    "pymongo.errors.OperationFailure: %s" % e
                ),
            )

    # TODO: The next three methods could be pulled out to form the basis
    # of a separate MonqoQuery class

    def combine_queries(self, query_a, query_b):
        """ Takes two db queries and applies db-specific syntax to produce
        the intersection.

        This is used because we can't just dump one set of query operators
        into another.

        Consider for example if the dataset contains a custom datasource
        pattern like --
           'filter': {'username': {'$exists': True}}

        If we simultaneously try to filter on the field `username`,
        then doing
            query_a.update(query_b)
        would lose information.

        This implementation of the function just combines everything in the
        two dicts using the `$and` operator.

        Note that this is exactly same as performing dict.update() except
        when multiple operators are operating on the /same field/.

        Example:
            combine_queries({'username': {'$exists': True}},
                            {'username': '******'})
        {'$and': [{'username': {'$exists': True}}, {'username': '******'}]}

        .. versionadded: 0.1.0
           Support for intelligent combination of db queries
        """
        # Chain the operations with the $and operator
        return {
            "$and": [
                {k: v} for k, v in itertools.chain(query_a.items(), query_b.items())
            ]
        }

    def get_value_from_query(self, query, field_name):
        """ For the specified field name, parses the query and returns
        the value being assigned in the query.

        For example,
            get_value_from_query({'_id': 123}, '_id')
        123

        This mainly exists to deal with more complicated compound queries
            get_value_from_query(
                {'$and': [{'_id': 123}, {'firstname': 'mike'}],
                '_id'
            )
        123

        .. versionadded: 0.1.0
           Support for parsing values embedded in compound db queries
        """
        if field_name in query:
            return query[field_name]
        elif "$and" in query:
            for condition in query["$and"]:
                if field_name in condition:
                    return condition[field_name]
        raise KeyError

    def query_contains_field(self, query, field_name):
        """ For the specified field name, does the query contain it?
        Used know whether we need to parse a compound query.

        .. versionadded: 0.1.0
           Support for parsing values embedded in compound db queries
        """
        try:
            self.get_value_from_query(query, field_name)
        except KeyError:
            return False
        return True

    def is_empty(self, resource):
        """ Returns True if resource is empty; False otherwise. If there is
        no predefined filter on the resource we're relying on the
        db.collection.count_documents. However, if we do have a predefined
        filter we have to fallback on the find() method, which can be much
        slower.

        .. versionchanged:: 0.6
           Support for multiple databases.

        .. versionadded:: 0.3
        """
        datasource, filter_, _, _ = self.datasource(resource)
        coll = self.pymongo(resource).db[datasource]
        try:
            if not filter_:
                # faster, but we can only afford it if there's now predefined
                # filter on the datasource.
                return coll.count_documents({}) == 0
            else:
                # fallback on find() since we have a filter to apply.
                try:
                    # need to check if the whole resultset is missing, no
                    # matter the IMS header.
                    del filter_[config.LAST_UPDATED]
                except:
                    pass
                return coll.count_documents(filter_) == 0
        except pymongo.errors.OperationFailure as e:
            # see comment in :func:`insert()`.
            self.app.logger.exception(e)
            abort(
                500,
                description=debug_error_message(
                    "pymongo.errors.OperationFailure: %s" % e
                ),
            )

    def _mongotize(self, source, resource, parse_objectid=False):
        """ Recursively iterates a JSON dictionary, turning RFC-1123 strings
        into datetime values and ObjectId-link strings into ObjectIds.

        .. versionchanged:: 0.3
           'query_objectid_as_string' allows to bypass casting string types
           to objectids.

        .. versionchanged:: 0.1.1
           Renamed from _jsondatetime to _mongotize, as it now handles
           ObjectIds too.

        .. versionchanged:: 0.1.0
           Datetime conversion was failing on Py2, since 0.0.9 :P

        .. versionchanged:: 0.0.9
           support for Python 3.3.

        .. versionadded:: 0.0.4
        """
        resource_def = config.DOMAIN[resource]
        schema = resource_def.get("schema")
        id_field = resource_def["id_field"]
        id_field_versioned = versioned_id_field(resource_def)
        query_objectid_as_string = resource_def.get("query_objectid_as_string", False)
        parse_objectid = parse_objectid or not query_objectid_as_string

        def try_cast(k, v, should_parse_objectid):
            try:
                return datetime.strptime(v, config.DATE_FORMAT)
            except:
                if k in (id_field, id_field_versioned) or should_parse_objectid:
                    try:
                        # Convert to unicode because ObjectId() interprets
                        # 12-character strings (but not unicode) as binary
                        # representations of ObjectId's.  See
                        # https://github.com/pyeve/eve/issues/508
                        try:
                            r = ObjectId(unicode(v))
                        except NameError:
                            # We're on Python 3 so it's all unicode already.
                            r = ObjectId(v)
                        return r
                    except:
                        return v
                else:
                    return v

        def get_schema_type(keys, schema):
            def dict_sub_schema(base):
                if base.get("type") == "dict":
                    return base.get("schema")
                return base

            if not isinstance(schema, dict):
                return None
            if not keys:
                return schema.get("type")

            k = keys[0]
            keys = keys[1:]
            schema_type = schema[k].get("type") if k in schema else None
            if schema_type == "list":
                if "items" in schema[k]:
                    items = schema[k].get("items") or []
                    possible_types = [get_schema_type(keys, item) for item in items]
                    if "objectid" in possible_types:
                        return "objectid"
                    else:
                        return next((t for t in possible_types if t), None)
                elif "schema" in schema[k]:
                    # recursively check the schema
                    return get_schema_type(keys, dict_sub_schema(schema[k]["schema"]))
            elif schema_type == "dict":
                if "schema" in schema[k]:
                    return get_schema_type(keys, dict_sub_schema(schema[k]["schema"]))
            else:
                return schema_type

        for k, v in source.items():
            keys = k.split(".")
            schema_type = get_schema_type(keys, schema)
            is_objectid = (schema_type == "objectid") or parse_objectid
            if isinstance(v, dict):
                self._mongotize(v, resource, is_objectid)
            elif isinstance(v, list):
                for i, v1 in enumerate(v):
                    if isinstance(v1, dict):
                        source[k][i] = self._mongotize(v1, resource)
                    else:
                        source[k][i] = try_cast(k, v1, is_objectid)
            elif isinstance(v, str_type):
                source[k] = try_cast(k, v, is_objectid)

        return source

    def _sanitize(self, resource, spec):
        """ Makes sure that only allowed operators are included in the query,
        aborts with a 400 otherwise.

        .. versionchanged:: 1.1.0
           Add mongo_query_whitelist config option to extend the list of
           supported operators

        .. versionchanged:: 0.5
           Abort with 400 if unsupported query operators are used. #387.
           DRY.

        .. versionchanged:: 0.0.9
           More informative error messages.
           Allow ``auth_username_field`` to be set to ``ID_FIELD``.

        .. versionadded:: 0.0.7
        """

        def sanitize_keys(spec):
            ops = set([op for op in spec.keys() if op[0] == "$"])
            known = Mongo.operators | set(
                config.DOMAIN[resource]["mongo_query_whitelist"]
            )

            unknown = ops - known
            if unknown:
                abort(
                    400,
                    description=debug_error_message(
                        "Query contains unknown or unsupported operators: %s"
                        % ", ".join(unknown)
                    ),
                )

            if set(spec.keys()) & set(config.MONGO_QUERY_BLACKLIST):
                abort(
                    400,
                    description=debug_error_message(
                        "Query contains operators banned in MONGO_QUERY_BLACKLIST"
                    ),
                )

        if isinstance(spec, dict):
            sanitize_keys(spec)
            for value in spec.values():
                self._sanitize(resource, value)
        if isinstance(spec, list):
            for value in spec:
                self._sanitize(resource, value)

        return spec

    def _convert_sort_request_to_dict(self, req):
        """ Converts the contents of a `ParsedRequest`'s `sort` property to
        a dict
        """
        client_sort = {}
        if req and req.sort:
            try:
                # assume it's mongo syntax (ie. ?sort=[("name", 1)])
                client_sort = ast.literal_eval(req.sort)
            except ValueError:
                # it's not mongo so let's see if it's a comma delimited string
                # instead (ie. "?sort=-age, name").
                sort = []
                for sort_arg in [s.strip() for s in req.sort.split(",")]:
                    if sort_arg[0] == "-":
                        sort.append((sort_arg[1:], -1))
                    else:
                        sort.append((sort_arg, 1))
                if len(sort) > 0:
                    client_sort = sort
            except Exception as e:
                self.app.logger.exception(e)
                abort(400, description=debug_error_message(str(e)))
        return client_sort

    def _convert_where_request_to_dict(self, resource, req):
        """ Converts the contents of a `ParsedRequest`'s `where` property to
        a dict
        """
        query = {}
        if req and req.where:
            try:
                query = self._sanitize(resource, json.loads(req.where))
            except HTTPException:
                # _sanitize() is raising an HTTP exception; let it fire.
                raise
            except:
                # couldn't parse as mongo query; give the python parser a shot.
                try:
                    query = parse(req.where)
                except ParseError:
                    abort(
                        400,
                        description=debug_error_message(
                            "Unable to parse `where` clause"
                        ),
                    )
        return query

    def _wc(self, resource):
        """ Syntactic sugar for the current collection write_concern setting.

        .. versionadded:: 0.0.8
        """
        return config.DOMAIN[resource]["mongo_write_concern"]

    def current_mongo_prefix(self, resource=None):
        """ Returns the active mongo_prefix that should be used to retrieve
        a valid PyMongo instance from the cache. If 'self.mongo_prefix' is set
        it has precedence over both endpoint (resource) and default drivers.
        This allows Auth classes (for instance) to override default settings to
        use a user-reserved db instance.

        Even a standard Flask view can set the mongo_prefix:

            from flask import g

            g.mongo_prefix = 'MONGO2'

        :param resource: endpoint for which a mongo prefix is needed.

        ..versionchanged:: 0.7
          Allow standard Flask views (@app.route) to set the mongo_prefix on
          their own.

        ..versionadded:: 0.6
        """

        # the hack below avoids passing the resource around, which would not be
        # an issue within this module but would force an update to the
        # eve.io.media.MediaStorage interface, possibly breaking compatibility
        # for other database implementations.

        auth = None
        try:
            if resource is None and request and request.endpoint:
                resource = request.endpoint[: request.endpoint.index("|")]
            if request and request.endpoint:
                auth = resource_auth(resource)
        except ValueError:
            pass

        px = auth.get_mongo_prefix() if auth else None

        if px is None:
            px = g.get("mongo_prefix", None)

        if px is None:
            if resource:
                px = config.DOMAIN[resource].get("mongo_prefix", "MONGO")
            else:
                px = "MONGO"

        return px

    def pymongo(self, resource=None, prefix=None):
        """ Returns an active PyMongo instance. If 'prefix' is defined then
        it has precedence over the endpoint ('resource') and/or
        'self.mongo_instance'.

        :param resource: endpoint for which a PyMongo instance is requested.
        :param prefix: PyMongo instance key. This has precedence over both
                       'resource' and eventual `self.mongo_prefix'.

        .. versionadded:: 0.6
        """
        px = prefix if prefix else self.current_mongo_prefix(resource=resource)

        if px not in self.driver:
            # instantiate and add to cache
            self.driver[px] = PyMongo(self.app, px)

        # important, we don't want to preserve state between requests
        self.mongo_prefix = None

        try:
            return self.driver[px]
        except Exception as e:
            raise ConnectionException(e)

    def get_collection_with_write_concern(self, datasource, resource):
        """ Returns a pymongo Collection with the desired write_concern
        setting.

        PyMongo 3.0+ collections are immutable, yet we still want to allow the
        maintainer to change the write concern setting on the fly, hence the
        clone.

        .. versionadded:: 0.6.1
        """
        wc = WriteConcern(config.DOMAIN[resource]["mongo_write_concern"]["w"])
        return self.pymongo(resource).db[datasource].with_options(write_concern=wc)