class Comment(Document): __collection__ = 'col' __database__ = 'comment' structure = { 'oid': unicode, #文章或产品id 'level': int, #评价级别 1- 5 'type': IS(0, 1), #0留言 1评论 'content': unicode, #内容 'imgs': [unicode], 'userId': unicode, 'appkey': unicode, 'date': OR(unicode, datetime.datetime), 'answer': unicode, 'reserved_1': unicode, # 预留字段1 'reserved_2': unicode, # 预留字段1 'reserved_3': unicode, # 预留字段1 'reserved_4': unicode, # 预留字段1 'del': int, #0 存在 1删除 } required = ['oid', 'type', 'content', 'appkey', 'userId'] validators = { 'oid': max_length(100), 'content': max_length(1000), 'answer': max_length(1000), } default_values = { 'del': 0, 'type': 0, 'date': datetime.datetime.now(), } use_dot_notation = True
class Type(Document): __collection__ = 'type' __database__ = 'app' structure = { 'level': int, 'name': unicode, 'dec': unicode, 'appkey': unicode, 'date': OR(unicode, datetime.datetime), 'type': IS(u'article', u'article_hot', u'shop', u'shop_hot', u'user'), 'parentID': unicode, 'reserved_1': unicode, #预留字段1 'reserved_2': unicode, #预留字段1 'reserved_3': unicode, #预留字段1 'reserved_4': unicode, #预留字段1 'del': int, #0 存在 1删除 } validators = { 'name': max_length(50), 'dec': max_length(10000), 'reserved_1': max_length(10000), 'reserved_2': max_length(10000), 'reserved_3': max_length(10000), 'reserved_4': max_length(10000), } default_values = { 'del': 0, 'date': datetime.datetime.now(), 'level': 1, 'parentID': u'', } use_dot_notation = True
class Page(Content): type = CONTENT_TYPE.PAGE structure = { 'author': User, 'type': int, 'title': unicode, 'slug': unicode, 'tags': list, 'status': IS(u'published', u'draft', u'deleted'), 'content': unicode, 'content_html': unicode, 'enable_comment': bool, 'comments': [ { 'id': int, 'user': User, 'text': unicode, 'created_at': datetime.datetime, 'responses': [{ 'id': int, 'user': User, 'text': unicode, 'created_at': datetime.datetime}] }], 'attachments': [{'type':unicode, 'src':unicode, \ 'thumb_src':unicode, 'filename': unicode}], 'created_at': datetime.datetime, 'updated_at': datetime.datetime } default_values = { 'enable_comment': False, 'comments': [], 'created_at': datetime.datetime.utcnow }
class Donation(BaseDocument): collection_name = 'donations' structure = { 'from': IS(User, unicode), 'for': User, 'from_account': BankAccount, 'for_account': BankAccount, 'transfer_no': unicode, 'amount': int, 'object': IS(Project, Article), # optional 'is_validated': bool, 'transferred_at': datetime.datetime, 'created_at': datetime.datetime } required_fields = ['from', 'for', 'transfer_no', 'amount'] default_values = { 'is_validated': False, 'created_at': datetime.datetime.utcnow } validators = {"amount": lambda x: x > 0}
class Topic(Document): __collection__ = 'topics' structure = { 'name': unicode, 'description': unicode, 'date': CustomDate(), 'weight': float, 'questionOrder': IS(u"hits", u"weight") } required_fields = ['name', 'weight', 'questionOrder'] default_values = {'date': datetime.utcnow} use_dot_notation = True
class PageHelpContent(Document): __collection__ = 'pageHelpContents' structure = { 'page': ObjectId, 'placement': IS(u"top", u"bottom", u"right", u"left"), 'order': int, 'content': unicode, 'isActive': bool } required_fields = ['page', 'placement', 'order', 'isActive'] default_values = {'isActive': True} use_dot_notation = True
class Project(MongoBaseItem): __database__ = "rongmofang" __collection__ = "project" structure = { "id": int, "project_type": IS(u"融资", u"转让"), "financial_already": unicode, # 项目融资金额 "financial_left": unicode, # 还需融资额 'project_name': unicode, 'project_region': unicode, "company_id": ObjectId, "guarantee_id": ObjectId, "profit_method": unicode, # 获取收益方式 "time_limit": unicode, # 融资期限 "risk_management": unicode, # 风险措施 "expected_interest_date": datetime, # 预计起息日 'interest_per_year': unicode, 'payback_date': datetime, 'capitl_useage': unicode, 'payback_source': unicode, 'additional': unicode, 'expected_profit': [{ "expected_pay_time": datetime, 'details': [{ "type": unicode, "amount": unicode, }], }], 'invest_records': [{ 'name': unicode, 'money': unicode, 'time': datetime, }] }
class Activity(BaseDocument): collection_name = 'activities' structure = { 'user': User, 'type': int, 'object': IS(Article, Project, Post, Blog), 'points': int, 'created_at': datetime.datetime } def score(self, user, object, activity): User.collection.update({'username': user.username}, \ {'$inc': { 'points': 1}})
class Info(MongoBaseItem): __database__ = "rongmofang" __collection__ = "info" structure = { "id": int, "type": IS(1, 2, 0), "title": unicode, "pub_time": datetime, "keywords": [unicode], "source": unicode, "content": unicode, }
class Img2(Document): __collection__ = 'col' __database__ = 'img' structure = { 'url': unicode, #路径 'type': IS(u'AD', u'RSC', u'OTHER'), # ad 广告 rsc 资源 other 'size': OR(int, float, unicode), #大小 'pf': unicode, #后缀 'name': unicode, # 后缀 'appkey': unicode, 'userid': unicode, 'date': OR(unicode, datetime.datetime), 'del': int, #0 存在 1删除 } required = ['url', 'pf', 'appkey'] validators = { 'url': max_length(100), 'userid': max_length(100), 'name': max_length(100), 'pf': max_length(10), } default_values = { 'del': 0, 'type': 'RSC', 'date': datetime.datetime.now(), } use_dot_notation = True @connection.register class Ad_imgs(Document): __collection__ = 'col' __database__ = 'ads' structure = { 'des': unicode, # 描述 'imgs': [{ 'url': unicode, 'tolink': unicode }], 'appkey': unicode, 'date': OR(unicode, datetime.datetime), 'del': int, # 0 存在 1删除 } required = ['appkey'] validators = {} default_values = { 'del': 0, 'date': datetime.datetime.now(), } use_dot_notation = True
class Volunteer(BaseDocument): collection_name = 'volunteers' structure = { 'user': User, 'approved_by': User, 'project': Project, 'status': IS(u'approved', u'pending', u'rejected'), 'asked_at': datetime.datetime, 'status_updated_at': datetime.datetime } required_fields = ['user', 'project'] default_values = { 'status': u'pending', 'asked_at': datetime.datetime.utcnow }
class Run(BackendDocument): STATE = Enum(u'undefined', u'pending', u'running', u'finished') use_autorefs = True __collection__ = 'runs' structure = { 'app': App, 'state': IS(*STATE.values_both_types()), 'executionStrategy': basestring, 'date_added': float } required_fields = ['app'] default_values = { 'date_added': time.time } indexes = [{ 'fields':['state'], }] def clean_doc(self): cp = super(Run, self).clean_doc() if 'app' in self and self.app: cp['app'] = str(self.app['_id']) return cp @classmethod def rebuild_doc_dict(cls, db, docDict): docDict = super(Run, cls).rebuild_doc_dict(db, docDict) if 'app' in docDict: appId = docDict['app'] try: appId = ObjectId(appId) except InvalidId: return docDict app = db.AppStoreApp.find_one({'_id':appId}) if not app: app = db.CydiaApp.find_one({'_id':appId}) docDict['app'] = app return docDict
class Member(OctobearDocument): __collection__ = 'members' structure = { 'sid': int, 'login': basestring, 'name': basestring, 'email': basestring, 'github': basestring, 'registered': bool, 'time_registered': datetime.datetime, 'role': IS(0, 1, 2, 3), # 0: student; 1: reader; 2: ta; 3: instructor 'grades': Set(ObjectId), # Set(Grade) 'group': ObjectId # Group } required_fields = ['sid', 'role', 'registered'] default_values = {'role': 0, 'registered': False} indexes = [ { 'fields': 'sid', 'unique': True, 'ttl': 0 } ]
class Collection(Document): __collection__ = 'collection' __database__ = 'shop' structure = { 'appkey': unicode, 'type': IS(u'collection', u'shopcard'), 'userId': unicode, 'productId': unicode, #产品Id 'date': OR(unicode, datetime.datetime), 'reserved_1': unicode, #预留字段1 'reserved_2': unicode, #预留字段1 'reserved_3': unicode, #预留字段1 'reserved_4': unicode, #预留字段1 'del': int, #0 存在 1删除 } validators = { 'appkey': max_length(200), 'userId': max_length(200), } default_values = { 'del': 0, 'date': datetime.datetime.now(), } use_dot_notation = True
class CircleAnnotation(Annotation): structure = {'type': IS(u'circle'), 'radius': int} required_fields = ['radius']
class Order(Document): __collection__ = 'order' __database__ = 'shop' structure = { 'user':unicode, #订单客户 'price': OR(float,int), #订单实付价格 'product': [{ #订单产品 '_id':unicode, 'title':unicode, #产品名称 'imgs':[], #产品图片 'costprice': OR(float, int), # 成本单价 'price': OR(float,int), # 产品单价 'saleprice': OR(float, int), # 产品促销价 'saleCode':unicode, # 优惠码 'colour': unicode, # 颜色 大小 'size': unicode, # 大小 'count':int, #购买数量 }], 'date': OR(unicode, datetime.datetime), 'receiveinfo':{ 'name': unicode, # 收件人名称 'mphone': unicode, # 手机号码 'phone': unicode, # 电话 'province': unicode, # 省 'city': unicode, # 市 'area': unicode, # 区域 'address': unicode, # 详细地址 'remake': unicode, # 备注 }, #收货信息 'status':IS(0,1,2,3,4), #0 待付款 1已付款 2,已发货 3.交易完成 4关闭交易 'refund': { #退款信息 'status': IS(0,1,2,3,4,5), # 退款状态 0 无退款 1申请退款 2同意退款 3拒绝退款 4退款完成,5关闭退款 'remake':[{ #卖退款备注 'user':unicode, 'msg':unicode, 'date': OR(unicode, datetime.datetime), }], 'price': OR(float, int), #退款金额 'products': list, # 退款产品 'express':{ #快递信息 'name':unicode, #快递名称 'code': unicode, # 快递单号 }, 'date': OR(unicode, datetime.datetime), }, 'express':{ #物流信息 'name': unicode, # 快递名称 'code': unicode, # 快递单号 }, 'remake': unicode, # 备注 'appkey':unicode, 'reserved_1':unicode, #预留字段1 支付订单号 'reserved_2':unicode, #预留字段1 'reserved_3':unicode, #预留字段1 'reserved_4':unicode, #预留字段1 'del': int,#0 存在 1删除 } validators = { 'user': max_length(200), 'refund.remake': max_length(200), 'refund.express.name': max_length(200), 'refund.express.code': max_length(200), 'remake': max_length(200), 'express.code': max_length(200), 'express.name': max_length(200), } default_values = { 'del': 0, 'date': datetime.datetime.now(), 'status': 0, 'refund.status': 0, } required = ['user', 'price', 'receiveinfo', 'status'] use_dot_notation = True
class User(BaseDocument): collection_name = 'users' structure = { # account info 'username': unicode, 'password_hashed': unicode, 'uid': unicode, 'avatar': unicode, 'logo': unicode, 'access_token': unicode, #fb=session_key 'auth_provider': IS(u'facebook', u'google', u'twitter', u'form'), 'status': IS(u'active', u'disabled', u'deleted'), 'reg_status': IS(u'verified', u'await'), 'type': IS(*USER_TYPE), 'is_admin': bool, 'is_verified': bool, 'featured': bool, 'last_login': datetime.datetime, # information 'sex': unicode, 'fullname': unicode, 'birthday_date': datetime.datetime, 'contact_person': unicode, 'phones': list, 'fax': list, 'address': unicode, 'email': unicode, 'website': unicode, 'document_scan': unicode, 'timezone': unicode, 'locale': unicode, 'tags': list, 'about': unicode, 'profile_content': unicode, 'profile_content_html': unicode, 'attachments': [{ 'type': unicode, 'src': unicode, 'thumb_src': unicode, 'filename': unicode }], # site-related 'following': list, 'followers': list, 'preferences': { 'enable_location': bool, 'send_email_on_writing': bool, }, 'badges': list, 'points': int, 'article_count': int, 'project_count': int, 'comment_count': int, 'donation_count': int, 'vote_up': int, 'vote_down': int, 'lat': unicode, 'lng': unicode, 'created_at': datetime.datetime, 'updated_at': datetime.datetime, } indexed_field = 'profile_content' required_fields = ['username'] sanitized_fields = ['address', 'email', 'website', 'about'] default_values = { 'status': u'active', 'timezone': u'Asia/Jakarta', 'is_admin': False, 'is_verified': False, 'featured': False, 'article_count': 0, 'project_count': 0, 'donation_count': 0, 'points': 0, 'created_at': datetime.datetime.utcnow, 'type': u'public' } indexes = [{'fields': 'username', 'unique': True}] def save(self, data=None, user=None, safe=True): if not data: super(User, self).save() return self.populate(data) self['updated_at'] = datetime.datetime.utcnow() if user and data.has_key('bank_accounts'): self.update_bank_accounts(user, data['bank_accounts']) new_doc = '_id' not in self super(User, self).save(safe=safe) self.post_save(data, new_doc) def post_save(self, data, new_doc): if self.indexed_field: payload = { 'id': self['_id'], 'title': self['username'], 'content': self[self.indexed_field], 'path': self.get_url(), 'type': self['type'], 'tags': self['tags'], 'created_at': self['created_at'], 'updated_at': self['updated_at'] } Queue.publish('index.user', payload) def remove(self): payload = {'id': self['_id']} Queue.publish('remove.user', payload) self['status'] = u'deleted' self.save() def update_bank_accounts(self, user, accounts): _accounts = list(user.get_bank_accounts()) prev_accounts = [acc['_id'] for acc in _accounts] updated_accounts = [] for acc in accounts: try: if acc[4] == "0": logging.warning("Adding account %s" % acc[0]) BankAccount.add_account(user, acc) elif acc[4] in prev_accounts: i = prev_accounts.index(acc[4]) #del(prev_accounts[i]) updated_accounts.append(acc[4]) if self.is_bank_data_dirty(acc, _accounts[i]): logging.warning("%s is dirty. Updating..." % acc[4]) BankAccount.update_account(acc) except: pass removed_accounts = set(prev_accounts).difference(set(updated_accounts)) for accid in list(removed_accounts): logging.warning("Removing %s" % accid) BankAccount.remove({'_id': accid}) def is_bank_data_dirty(self, current, _prev): prev = [] fields = BankAccount.fields[:] fields.append('_id') for field in fields: prev.append(_prev[field]) return prev != current @classmethod def filter_valid_accounts(cls, accounts): return [account for account in accounts if len(account) > 4] def get_bank_accounts(self): """ not using self.related.bank_accounts since spec produced includes checking index field ($exists: true) that somehow skewing result """ spec = {'owner': DBRef(self.collection_name, self._id)} return BankAccount.collection.find(spec) @classmethod def get_most_active(self): js_update_points = """ function update_points() { db.users.find().forEach(function(u) { u.points = 10*u.project_count+5*u.article_count; db.users.save(u);}) } """ User.collection.database.eval(js_update_points) return User.all({},['username','avatar','fullname','points','article_count','project_count'])\ .sort("points", -1).limit(5) def process_inline(self, field, src): if field not in ['profile_content']: return src return self.process_inline_attachments(src) def get_url(self): return "/profile/" + self['username'] def increment_karma(self, kind, amount): pass
class PointerAnnotation(Annotation): structure = {'type': IS(u'pointer')}
class Article(Content): type = CONTENT_TYPE.ARTICLE structure = { 'type': int, 'author': User, 'status': IS(u'published', u'draft', u'deleted'), 'featured': bool, 'title': unicode, 'slug': unicode, 'tags': list, 'excerpt': unicode, 'content': unicode, 'content_html': unicode, 'enable_comment': bool, 'comments': [{ 'id': int, 'user': User, 'text': unicode, 'created_at': datetime.datetime, 'responses': [{ 'id': int, 'user': User, 'text': unicode, 'created_at': datetime.datetime }] }], 'attachments': [{ 'type': unicode, 'src': unicode, 'thumb_src': unicode, 'filename': unicode }], 'view_count': int, 'vote_up': int, 'vote_down': int, 'lat': unicode, 'lng': unicode, 'created_at': datetime.datetime, 'updated_at': datetime.datetime } api_fields = [ 'title', 'slug', 'excerpt', 'content', 'view_count', 'tags', 'created_at' ] default_values = { 'enable_comment': True, 'featured': False, 'view_count': 0, 'vote_up': 0, 'vote_down': 0, 'status': u'published', 'comments': [], 'created_at': datetime.datetime.utcnow, 'updated_at': datetime.datetime.utcnow } indexes = [{'fields': ['type', 'slug'], 'unique': True}] def post_save(self, data, new_doc): if new_doc: User.collection.update({'username': self.author.username}, {'$inc': { 'article_count': 1 }}) super(Article, self).post_save(data, new_doc) def post_remove(self): User.collection.update({'username': self.author.username}, {'$inc': { 'article_count': -1 }})
DATA_TYPE_CHOICES = ("None", "bool", "basestring", "unicode", "int", "float", "long", "datetime.datetime", "list", "dict", "ObjectId", "IS()") TYPES_LIST = [ 'GSystemType', 'RelationType', 'AttributeType', 'MetaType', 'ProcessType' ] my_doc_requirement = u'storing_orignal_doc' reduced_doc_requirement = u'storing_reduced_doc' to_reduce_doc_requirement = u'storing_to_be_reduced_doc' indexed_word_list_requirement = u'storing_indexed_words' # CUSTOM DATA-TYPE DEFINITIONS STATUS_CHOICES_TU = IS(u'DRAFT', u'HIDDEN', u'PUBLISHED', u'DELETED', u'MODERATION') STATUS_CHOICES = tuple(str(qtc) for qtc in STATUS_CHOICES_TU) QUIZ_TYPE_CHOICES_TU = IS(u'Short-Response', u'Single-Choice', u'Multiple-Choice') QUIZ_TYPE_CHOICES = tuple(str(qtc) for qtc in QUIZ_TYPE_CHOICES_TU) # Designate a root folder for HashFS. If the folder does not exists already, it will be created. # Set the `depth` to the number of subfolders the file's hash should be split when saving. # Set the `width` to the desired width of each subfolder. gfs = HashFS(MEDIA_ROOT, depth=3, width=1, algorithm='sha256') # gfs: gstudio file system # DATABASE Variables db = get_database()
class Project(Content): type = CONTENT_TYPE.PROJECT structure = { 'type': int, 'author': User, 'status': IS(u'published', u'draft', u'deleted'), 'featured': bool, 'title': unicode, 'slug': unicode, 'tags': list, 'enable_comment': bool, 'comments': [{ 'id': unicode, 'user': User, 'text': unicode, 'created_at': datetime.datetime, 'responses': [{ 'id': int, 'user': User, 'text': unicode, 'created_at': datetime.datetime }] }], 'attachments': [{ 'type': unicode, 'src': unicode, 'thumb_src': unicode, 'filename': unicode }], 'goal': unicode, 'content': unicode, 'content_html': unicode, 'state': IS(u'planning', u'running', u'completed', u'cancelled', u'unknown'), 'need_volunteer': bool, 'volunteer_tags': list, 'need_donation': bool, 'show_map': bool, 'enable_chat': bool, 'donation_amount_needed': int, 'donation_amount': float, 'validators': [{ 'user': User, 'comment': unicode }], 'volunteers': list, 'supporters': list, 'donaters': list, 'events': [{ 'date': datetime.datetime, 'description': unicode }], 'view_count': int, 'vote_up': int, 'vote_down': int, 'lat': unicode, 'lng': unicode, 'created_at': datetime.datetime, 'updated_at': datetime.datetime } required_fields = ['author', 'title', 'content', 'goal'] api_fields = [ 'title', 'slug', 'excerpt', 'content', 'view_count', 'tags', 'created_at' ] default_values = { 'enable_comment': True, 'need_donation': False, 'need_volunteer': False, 'show_map': False, 'enable_chat': False, 'featured': False, 'status': u'published', 'state': u'planning', 'comments': [], 'view_count': 0, 'vote_up': 0, 'vote_down': 0, 'donation_amount_needed': 0, 'created_at': datetime.datetime.utcnow, 'updated_at': datetime.datetime.utcnow } indexes = [{'fields': 'slug', 'unique': True}] def post_save(self, data, new_doc): if new_doc: User.collection.update({'username': self.author.username}, {'$inc': { 'project_count': 1 }}) super(Project, self).post_save(data, new_doc) def post_remove(self): User.collection.update({'username': self.author.username}, {'$inc': { 'project_count': -1 }})
class Cache(Simpledoc): collection_name = 'caches' structure = {'value': IS(dict, bool, unicode, list), 'expire': float} default_values = {'expire': 0.0}
class BadMyDoc(SchemaDocument): structure = {"bla": IS(('bla', ), 3)}
class MyDoc(SchemaDocument): structure = {"foo": IS(u'spam', u'eggs'), "bar": IS(u'3', 3)}
class Job(BackendDocument): STATE = Enum(u'undefined', u'pending', u'running', u'finished', u'failed') TYPE = Enum(u'run_app', u'install_app') use_autorefs = True __collection__ = 'jobs' structure = { 'type': IS(*TYPE.values_both_types()), 'state': IS(*STATE.values_both_types()), 'jobInfo': dict, #TODO accountId, bundleId, storeCountry, appType{AppStoreApp,CydiaApp}, executionStrategy{DefaultExecution,OpenCloseExecution,RandomExecution,SmartExecution} 'worker': Worker, 'device': Device, 'date_added': float } required_fields = ['type', 'state', 'jobInfo'] default_values = { 'date_added': time.time, 'state': STATE.UNDEFINED } indexes = [{ 'fields':['type', 'state'], }] def clean_doc(self): cp = super(Job, self).clean_doc() if 'worker' in self and self.worker: cp['worker'] = str(self.worker['_id']) if 'device' in self and self.device: cp['device'] = str(self.device['udid']) return cp @classmethod def rebuild_doc_dict(cls, db, docDict): docDict = super(Job, cls).rebuild_doc_dict(db, docDict) if 'worker' in docDict: workerId = docDict['worker'] try: workerId = ObjectId(workerId) except InvalidId: return docDict worker = db.Worker.find_one({'_id':workerId}) docDict['worker'] = worker if 'device' in docDict: deviceId = docDict['device'] device = db.Device.find_one({'udid':deviceId}) if device: docDict['device'] = device else: logger.debug('given string %s is not a device udid' % deviceId) try: deviceId = ObjectId(deviceId) except InvalidId: logger.debug('given string %s is not a deviceId' % deviceId) device = db.Device.find_one({'_id':deviceId}) if device: docDict['device'] = device return docDict def can_run_on_device(self, device): if self.type == Job.TYPE.RUN_APP: jobInfo = self.jobInfo if 'accountId' in jobInfo: for acc in device.accounts: if jobInfo['accountId'] == acc.uniqueIdentifier: return True return False if 'storeCountry' in jobInfo: country = jobInfo['storeCountry'] for acc in device.accounts: if country == acc.storeCountry: return True return False return True