def pre_allocate_expr(self, context): # TODO: too complex, not check hackathon_id = context.hackathon_id self.log.debug("executing pre_allocate_expr for hackathon %s " % hackathon_id) hackathon = Hackathon.objects(id=hackathon_id).first() hackathon_templates = hackathon.templates for template in hackathon_templates: try: template = template pre_num = int(hackathon.config.get(HACKATHON_CONFIG.PRE_ALLOCATE_NUMBER, 1)) query = Q(status=EStatus.STARTING) | Q(status=EStatus.RUNNING) curr_num = Experiment.objects(user=None, hackathon=hackathon, template=template).filter(query).count() self.log.debug("pre_alloc_exprs: pre_num is %d, curr_num is %d, remain_num is %d " % (pre_num, curr_num, pre_num - curr_num)) # TODO Should support VE_PROVIDER.K8S only in future after k8s Template is supported # if template.provider == VE_PROVIDER.K8S: if curr_num < pre_num: start_num = Experiment.objects(user=None, template=template, status=EStatus.STARTING).count() allowed_currency = int(hackathon.config.get(HACKATHON_CONFIG.PRE_ALLOCATE_CONCURRENT, 1)) if start_num >= allowed_currency: self.log.debug( "there are already %d Experiments starting, will check later ... " % allowed_currency) return else: remain_num = min(allowed_currency, pre_num) - start_num self.log.debug( "no starting template: %s , remain num is %d ... " % (template.name, remain_num)) self.start_pre_alloc_exprs(None, template.name, hackathon.name, remain_num) break except Exception as e: self.log.error(e) self.log.error("check default experiment failed")
def get_hackathon_list(self, args): # get values from request's QueryString page = int(args.get("page", 1)) per_page = int(args.get("per_page", 20)) order_by = args.get("order_by", "create_time") status = args.get("status") name = args.get("name") # build query by search conditions and order_by status_filter = Q() name_filter = Q() condition_filter = Q() order_by_condition = '-id' if status: status_filter = Q(status=status) if name: name_filter = Q(name__contains=name) if order_by == 'create_time': # 最新发布 order_by_condition = '-create_time' elif order_by == 'event_start_time': # 即将开始 order_by_condition = '-event_start_time' elif order_by == 'registered_users_num': # 人气热点 # hackathons with zero registered users would not be shown. hot_hackathon_stat = HackathonStat.objects( type=HACKATHON_STAT.REGISTER, count__gt=0).order_by('-count') hot_hackathon_list = [ stat.hackathon.id for stat in hot_hackathon_stat ] condition_filter = Q(id__in=hot_hackathon_list) else: order_by_condition = '-id' # perform db query with pagination pagination = Hackathon.objects(status_filter & name_filter & condition_filter).order_by( order_by_condition).paginate( page, per_page) hackathon_list = pagination.items hackathon_stat = HackathonStat.objects(hackathon__in=hackathon_list) user = None user_hackathon = [] team = [] if self.user_manager.validate_login(): user = g.user user_hackathon = UserHackathon.objects( user=user, hackathon__in=hackathon_list) team = Team.objects(members__user=user, hackathon__in=hackathon_list) def func(hackathon): return self.__fill_hackathon_detail(hackathon, user, hackathon_stat, user_hackathon, team) # return serializable items as well as total count return self.util.paginate(pagination, func)
def create_new_hackathon(self, context): """Create new hackathon based on the http body Hackathon name is unique so duplicated names are not allowd. :type context: Context :param context: the body of http request that contains fields to create a new hackathon :rtype: dict """ if Hackathon.objects(name=context.name).count() > 0: raise PreconditionFailed("hackathon name already exists") self.log.debug("add a new hackathon:" + context.name) new_hack = self.__create_hackathon(g.user, context) self.create_hackathon_notice( new_hack.id, HACK_NOTICE_EVENT.HACK_CREATE, HACK_NOTICE_CATEGORY.HACKATHON) # hackathon create # init data is for local only if self.util.is_local(): self.__create_default_data_for_local(new_hack) return new_hack.dic()
def check_hackathon_for_pre_allocate_expr(self): """Check all hackathon for pre-allocate Add an interval job for hackathon if it's pre-allocate is enabled. Otherwise try to remove the schedule job """ hackathon_list = Hackathon.objects() for hack in hackathon_list: job_id = "pre_allocate_expr_" + str(hack.id) is_job_exists = self.scheduler.has_job(job_id) if self.__is_pre_allocate_enabled(hack): if is_job_exists: self.log.debug( "pre_allocate job already exists for hackathon %s" % str(hack.name)) continue self.log.debug("add pre_allocate job for hackathon %s" % str(hack.name)) next_run_time = self.util.get_now() + timedelta( seconds=(20 * random.random())) pre_allocate_interval = self.__get_pre_allocate_interval(hack) self.scheduler.add_interval( feature="expr_manager", method="pre_allocate_expr", id=job_id, context=Context(hackathon_id=hack.id), next_run_time=next_run_time, seconds=pre_allocate_interval) elif is_job_exists: self.log.debug( "remove job for hackathon %s since pre_allocate is disabled" % str(hack.id)) self.scheduler.remove_job(job_id) return True
def get_docker_host_server(self, context): hackathon = Hackathon.objects( id=context.hackathon_id).no_dereference().first() try: host_resp = self.docker_host_manager.get_available_docker_host( hackathon) except Exception as e: self.log.error(e) host_resp = Context(state=DHS_QUERY_STATE.ONGOING) context.trial = context.get("trial", 0) + 1 if host_resp.state == DHS_QUERY_STATE.SUCCESS: # assign ports self.__assign_ports(context, host_resp.docker_host_server) elif host_resp.state == DHS_QUERY_STATE.ONGOING and context.trial < 20: # tried up to 20 times self.log.debug( "host servers are all busy, %d times tried, will retry in 3 seconds" % context.trial) self.scheduler.add_once(FEATURE, "get_docker_host_server", context, seconds=3) else: self.log.error("no available host server") self._on_virtual_environment_failed(context)
def get_entitled_hackathons_list(self, user): """Get hackathon id list that specific user is entitled to manage :type user_id: int :param user_id: id of user :rtype: list :return list of hackathon simple """ user_filter = Q() if not user.is_super: user_filter = Q(user=user, role=HACK_USER_TYPE.ADMIN) hids = [uh.hackathon.id for uh in UserHackathon.objects(user_filter).no_dereference().only("hackathon")] hack_list = Hackathon.objects(id__in=hids).only( 'name', 'display_name', 'ribbon', 'short_description', 'location', 'banners', 'status', 'creator', 'type', 'config', 'event_start_time', 'event_end_time').order_by("-event_end_time") all_hackathon = [h.dic() for h in hack_list] return all_hackathon
def get_recyclable_hackathon_list(self): # todo filter hackathons by hackathon.config in a db-level if possible hackathons = Hackathon.objects(status=HACK_STATUS.ONLINE, event_start_time__lt=self.util.get_now(), event_end_time__gt=self.util.get_now() ).all() return filter(lambda h: self.is_recycle_enabled(h), hackathons)
def check_hackathon_for_pre_allocate_expr(self): """Check all hackathon for pre-allocate Add an interval job for hackathon if it's pre-allocate is enabled. Otherwise try to remove the schedule job """ hackathon_list = Hackathon.objects() for hack in hackathon_list: job_id = "pre_allocate_expr_" + str(hack.id) is_job_exists = self.scheduler.has_job(job_id) if self.__is_pre_allocate_enabled(hack): if is_job_exists: self.log.debug("pre_allocate job already exists for hackathon %s" % str(hack.name)) continue self.log.debug("add pre_allocate job for hackathon %s" % str(hack.name)) next_run_time = self.util.get_now() + timedelta(seconds=(20 * random.random())) pre_allocate_interval = self.__get_pre_allocate_interval(hack) self.scheduler.add_interval(feature="expr_manager", method="pre_allocate_expr", id=job_id, context=Context(hackathon_id=hack.id), next_run_time=next_run_time, seconds=pre_allocate_interval ) elif is_job_exists: self.log.debug("remove job for hackathon %s since pre_allocate is disabled" % str(hack.id)) self.scheduler.remove_job(job_id) return True
def get_recyclable_hackathon_list(self): # todo filter hackathons by hackathon.config in a db-level if possible hackathons = Hackathon.objects( status=HACK_STATUS.ONLINE, event_start_time__lt=self.util.get_now(), event_end_time__gt=self.util.get_now()).all() return filter(lambda h: self.is_recycle_enabled(h), hackathons)
def get_hackathon_by_id(self, hackathon_id): """Query hackathon by id :type hackathon_id: str or ObjectId are both ok :param hackathon_id: _id of hackathon :return hackathon instance or None """ return Hackathon.objects(id=hackathon_id).first()
def get_all_granted_awards(self, limit): teams = Team.objects.all() teams_with_awards = [team for team in teams if not team.awards == []] teams_with_awards.sort(key=lambda t: ( t.hackathon.id, Hackathon.objects(id=t.hackathon.id, awards__id=t.awards[0]).first().awards.get(id=t.awards[0]).level ), reverse=True) # sort by hackathon and then sort by award level. teams_with_awards = teams_with_awards[0: int(limit)] return [self.__get_hackathon_and_show_detail(team) for team in teams_with_awards]
def get_certificates_by_expr(self, expr_id): """Get certificates by experiment id """ # expr = self.db.get_object(Experiment, expr_id) expr = Experiment.objects(id=expr_id) # hak = self.db.find_all_objects_by(HackathonAzureKey, hackathon_id=expr.hackathon_id) hak = Hackathon.objects(id=expr.hackathon_id).first().azure_keys[0] if not hak: raise Exception("no azure key configured") return map(lambda key: self.db.get_object(AzureKey, key.azure_key_id), hak)
def schedule_pre_allocate_host_server_job(self): """ Schedule pre-allocate host server for every hackathon found in DB table:hackathon """ self.log.debug('Begin to check host server and prepare resource.') min_avavilabe_container = 5 for hackathon in Hackathon.objects(): if self.__exist_request_host_server_by_hackathon_id(min_avavilabe_container, hackathon.id): continue if not self.start_new_docker_host_vm(hackathon): self.log.error('Schedule pre-allocate host server for hackathon:%s failed.' % hackathon.name)
def get_all_granted_awards(self, limit): teams = Team.objects().all() teams_with_awards = [team for team in teams if not team.awards == []] teams_with_awards.sort(key=lambda t: ( t.hackathon.id, Hackathon.objects(id=t.hackathon.id, awards__id=t.awards[0]).first().awards.get(id=t.awards[0]).level ), reverse=True) # sort by hackathon and then sort by award level. teams_with_awards = teams_with_awards[0: int(limit)] return [self.__get_hackathon_and_show_detail(team) for team in teams_with_awards]
def get_hackathon_list(self, args): # get values from request's QueryString page = int(args.get("page", 1)) per_page = int(args.get("per_page", 20)) order_by = args.get("order_by", "create_time") status = args.get("status") name = args.get("name") # build query by search conditions and order_by status_filter = Q() name_filter = Q() condition_filter = Q() order_by_condition = '-id' if status: status_filter = Q(status=status) if name: name_filter = Q(name__contains=name) if order_by == 'create_time': # 最新发布 order_by_condition = '-create_time' elif order_by == 'event_start_time': # 即将开始 order_by_condition = '-event_start_time' elif order_by == 'registered_users_num': # 人气热点 # hackathons with zero registered users would not be shown. hot_hackathon_stat = HackathonStat.objects(type=HACKATHON_STAT.REGISTER, count__gt=0).order_by('-count') hot_hackathon_list = [stat.hackathon.id for stat in hot_hackathon_stat] condition_filter = Q(id__in=hot_hackathon_list) else: order_by_condition = '-id' # perform db query with pagination pagination = Hackathon.objects(status_filter & name_filter & condition_filter).order_by( order_by_condition).paginate(page, per_page) hackathon_list = pagination.items hackathon_stat = HackathonStat.objects(hackathon__in=hackathon_list) user = None user_hackathon = [] team = [] if self.user_manager.validate_login(): user = g.user user_hackathon = UserHackathon.objects(user=user, hackathon__in=hackathon_list) team = Team.objects(members__user=user, hackathon__in=hackathon_list) def func(hackathon): return self.__fill_hackathon_detail(hackathon, user, hackathon_stat, user_hackathon, team) # return serializable items as well as total count return self.util.paginate(pagination, func)
def get_hackathon_by_name(self, name): """Get hackathon accoring the unique name :type name: str|unicode :param name: name of hackathon :rtype: Hackathon :return hackathon instance if found else None """ if not name: return None return Hackathon.objects(name=name).first()
def schedule_pre_allocate_host_server_job(self): """ Schedule pre-allocate host server for every hackathon found in DB table:hackathon """ self.log.debug('Begin to check host server and prepare resource.') min_avavilabe_container = 5 for hackathon in Hackathon.objects(): if self.__exist_request_host_server_by_hackathon_id( min_avavilabe_container, hackathon.id): continue if not self.start_new_docker_host_vm(hackathon): self.log.error( 'Schedule pre-allocate host server for hackathon:%s failed.' % hackathon.name)
def get_entitled_hackathons_list(self, user): """Get hackathon id list that specific user is entitled to manage :rtype: list :return list of hackathon simple """ if not user.is_super: hack_list = UserHackathon.objects(user=user, role=HACK_USER_TYPE.ADMIN).distinct("hackathon") hack_list.sort(key=lambda s: s.create_time, reverse=True) else: hack_list = Hackathon.objects().all().order_by("-create_time") all_hackathon = [h.dic() for h in hack_list] return all_hackathon
def get_entitled_hackathons_list(self, user): """Get hackathon id list that specific user is entitled to manage :rtype: list :return list of hackathon simple """ if not user.is_super: hack_list = UserHackathon.objects( user=user, role=HACK_USER_TYPE.ADMIN).distinct("hackathon") hack_list.sort(key=lambda s: s.create_time, reverse=True) else: hack_list = Hackathon.objects().all().order_by("-create_time") all_hackathon = [h.dic() for h in hack_list] return all_hackathon
def validate_hackathon_name(self): if HTTP_HEADER.HACKATHON_NAME in request.headers: try: hackathon_name = request.headers[HTTP_HEADER.HACKATHON_NAME] hackathon = Hackathon.objects(name=hackathon_name).first() if hackathon: g.hackathon = hackathon return True else: self.log.debug("cannot find hackathon by name %s" % hackathon_name) return False except Exception as ex: self.log.error(ex) self.log.debug("hackathon_name invalid") return False else: self.log.debug("hackathon_name not found in headers") return False
def __load_azure_key_id(self, context): # todo which key to use? how to support multi subscription? azure_key = None if "azure_key_id" in context: azure_key = AzureKey.objects(id=context.azure_key_id).first() if not azure_key: expr = Experiment.objects(id=context.experiment_id).only("azure_key").first() azure_key = expr.azure_key if not azure_key: hackathon = Hackathon.objects(id=context.hackathon_id).first() if not hackathon or (len(hackathon.azure_keys) == 0): raise Exception("no azure key configured") azure_key = hackathon.azure_keys[0] context.azure_key_id = azure_key.id return azure_key
def pre_allocate_expr(self, context): # TODO: too complex, not check hackathon_id = context.hackathon_id self.log.debug("executing pre_allocate_expr for hackathon %s " % hackathon_id) hackathon = Hackathon.objects(id=hackathon_id).first() hackathon_templates = hackathon.templates for template in hackathon_templates: try: template = template pre_num = int(hackathon.config.get("pre_allocate_number", 1)) query = Q(status=EStatus.STARTING) | Q(status=EStatus.RUNNING) curr_num = Experiment.objects(user=None, hackathon=hackathon, template=template).filter(query).count() if template.provider == VE_PROVIDER.AZURE: if curr_num < pre_num: remain_num = pre_num - curr_num start_num = Experiment.objects(user=None, template=template, status=EStatus.STARTING).count() if start_num > 0: self.log.debug("there is an azure env starting, will check later ... ") return else: self.log.debug( "no starting template: %s , remain num is %d ... " % (template.name, remain_num)) self.start_expr(None, template.name, hackathon.name) break elif template.provider == VE_PROVIDER.DOCKER: if hackathon.config.get('cloud_provider') == CLOUD_PROVIDER.ALAUDA: # don't create pre-env if alauda used continue self.log.debug( "template name is %s, hackathon name is %s" % (template.name, hackathon.name)) if curr_num < pre_num: remain_num = pre_num - curr_num start_num = Experiment.objects(user=None, template=template, status=EStatus.STARTING).count() if start_num > 0: self.log.debug("there is an docker container starting, will check later ... ") return self.log.debug("no idle template: %s, remain num is %d ... " % (template.name, remain_num)) self.start_expr(None, template.name, hackathon.name) break except Exception as e: self.log.error(e) self.log.error("check default experiment failed")
def get_docker_host_server(self, context): hackathon = Hackathon.objects(id=context.hackathon_id).no_dereference().first() try: host_resp = self.docker_host_manager.get_available_docker_host(hackathon) except Exception as e: self.log.error(e) host_resp = Context(state=DHS_QUERY_STATE.ONGOING) context.trial = context.get("trial", 0) + 1 if host_resp.state == DHS_QUERY_STATE.SUCCESS: # assign ports self.__assign_ports(context, host_resp.docker_host_server) elif host_resp.state == DHS_QUERY_STATE.ONGOING and context.trial < 20: # tried up to 20 times self.log.debug("host servers are all busy, %d times tried, will retry in 3 seconds" % context.trial) self.scheduler.add_once(FEATURE, "get_docker_host_server", context, seconds=3) else: self.log.debug("no available host server") self._on_virtual_environment_failed(context)
def get_hackathon_list(self, args): # get values from request's QueryString page = int(args.get("page", 1)) per_page = int(args.get("per_page", 20)) order_by = args.get("order_by", "create_time") status = args.get("status") name = args.get("name") # build query by search conditions and order_by status_filter = Q() name_filter = Q() order_by_condition = '-id' if status: status_filter = Q(status=status) if name: name_filter = Q(name__contains=name) if order_by == 'create_time': order_by_condition = '-create_time' elif order_by == 'event_start_time': order_by_condition = '-event_start_time' elif order_by == 'registered_users_num': # hackathons with zero registered users would not be shown. # TODO pass else: order_by_condition = '-id' # perform db query with pagination pagination = Hackathon.objects(status_filter & name_filter).order_by(order_by_condition).paginate(page, per_page) user = None if self.user_manager.validate_login(): user = g.user def func(hackathon): return self.__get_hackathon_detail(hackathon, user) # return serializable items as well as total count return self.util.paginate(pagination, func)
def __get_sms_object(self, hackathon_id): """ Get ServiceManagementService object by Azure account which is related to hackathon_id :param hackathon_id: the id of hackathon :type hackathon_id: integer :return: ServiceManagementService object :rtype: class 'azure.servicemanagement.servicemanagementservice.ServiceManagementService' """ hackathon_azure_keys = Hackathon.objects(id=hackathon_id).first().azure_keys if len(hackathon_azure_keys) == 0: self.log.error('Found no azure key with Hackathon:%d' % hackathon_id) return None hackathon_azure_key = hackathon_azure_keys[0] sms = ServiceManagementService(hackathon_azure_key.subscription_id, hackathon_azure_key.get_local_pem_url(), host=hackathon_azure_key.management_host) return sms
def create_new_hackathon(self, context): """Create new hackathon based on the http body Hackathon name is unique so duplicated names are not allowd. :type context: Context :param context: the body of http request that contains fields to create a new hackathon :rtype: dict """ if Hackathon.objects(name=context.name).count() > 0: raise PreconditionFailed("hackathon name already exists") self.log.debug("add a new hackathon:" + context.name) new_hack = self.__create_hackathon(g.user, context) # init data is for local only if self.util.is_local(): self.__create_default_data_for_local(new_hack) self.create_hackathon_notice(new_hack.id, HACK_NOTICE_EVENT.HACK_CREATE, HACK_NOTICE_CATEGORY.HACKATHON) return new_hack.dic()
def __get_sms_object(self, hackathon_id): """ Get ServiceManagementService object by Azure account which is related to hackathon_id :param hackathon_id: the id of hackathon :type hackathon_id: integer :return: ServiceManagementService object :rtype: class 'azure.servicemanagement.servicemanagementservice.ServiceManagementService' """ hackathon_azure_keys = Hackathon.objects( id=hackathon_id).first().azure_keys if len(hackathon_azure_keys) == 0: self.log.error('Found no azure key with Hackathon:%d' % hackathon_id) return None hackathon_azure_key = hackathon_azure_keys[0] sms = ServiceManagementService( hackathon_azure_key.subscription_id, hackathon_azure_key.get_local_pem_url(), host=hackathon_azure_key.management_host) return sms
def get_hackathon_notice_list(self, body): """ list hackathon notices, notices are paginated, can be filtered by hackathon_name, event and category, can be ordered by update_time, event and category. :type body: Context :param body: valid key/values(all key/values are optional) body = { hackathon_name: string, // filter by hackathon_name, default unfiltered category: 'int[,int...]', // filter by category, default unfiltered event: 'int[,int...]', // filter by event, default unfiltered order_by: 'time' | 'event' | 'category', // order by update_time, event, category, default by time page: int, // page number after pagination, start from 1, default 1 per_page: int // items per page, default 1000 } :return: json style text, see util.Utility ::Example: : body = { order_by: 'time', category: '1,2,3', page: 1, per_page: 6 } search first 6 notices ordered by time, filtered by: category in [1,2,3] : body = { hackathon_name: 'hackathon', event: '1', order_by: 'event' } search first 1000 notices ordered by event, filtered by event == 1 and hackathon_name == 'hackathon' """ hackathon_name = body.get("hackathon_name") notice_category = body.get("category") notice_event = body.get("event") order_by = body.get("order_by", "time") page = int(body.get("page", 1)) per_page = int(body.get("per_page", 1000)) hackathon_filter = Q() category_filter = Q() event_filter = Q() order_by_condition = '-update_time' if hackathon_name: hackathon = Hackathon.objects(name=hackathon_name).only('name').first() if hackathon: hackathon_filter = Q(hackathon=hackathon) else: return not_found('hackathon_name not found') if notice_category: notice_category_tuple = tuple([int(category) for category in notice_category.split(',')]) category_filter = Q(category__in=notice_category_tuple) if notice_event: notice_event_tuple = tuple([int(event) for event in notice_event.split(',')]) event_filter = Q(event__in=notice_event_tuple) if order_by == 'category': order_by_condition = '+category' elif order_by == 'event': order_by_condition = '+event' else: order_by_condition = '-update_time' pagination = HackathonNotice.objects( hackathon_filter & category_filter & event_filter ).order_by( order_by_condition ).paginate(page, per_page) def func(hackathon_notice): return hackathon_notice.dic() # return serializable items as well as total count return self.util.paginate(pagination, func)
def pre_allocate_expr(self, context): # TODO: too complex, not check hackathon_id = context.hackathon_id self.log.debug("executing pre_allocate_expr for hackathon %s " % hackathon_id) hackathon = Hackathon.objects(id=hackathon_id).first() hackathon_templates = hackathon.templates for template in hackathon_templates: try: template = template pre_num = int(hackathon.config.get("pre_allocate_number", 1)) query = Q(status=EStatus.STARTING) | Q(status=EStatus.RUNNING) curr_num = Experiment.objects( user=None, hackathon=hackathon, template=template).filter(query).count() if template.provider == VE_PROVIDER.AZURE: if curr_num < pre_num: remain_num = pre_num - curr_num start_num = Experiment.objects( user=None, template=template, status=EStatus.STARTING).count() if start_num > 0: self.log.debug( "there is an azure env starting, will check later ... " ) return else: self.log.debug( "no starting template: %s , remain num is %d ... " % (template.name, remain_num)) self.start_expr(None, template.name, hackathon.name) break elif template.provider == VE_PROVIDER.DOCKER: if hackathon.config.get( 'cloud_provider') == CLOUD_PROVIDER.ALAUDA: # don't create pre-env if alauda used continue self.log.debug( "template name is %s, hackathon name is %s" % (template.name, hackathon.name)) if curr_num < pre_num: remain_num = pre_num - curr_num start_num = Experiment.objects( user=None, template=template, status=EStatus.STARTING).count() if start_num > 0: self.log.debug( "there is an docker container starting, will check later ... " ) return self.log.debug( "no idle template: %s, remain num is %d ... " % (template.name, remain_num)) self.start_expr(None, template.name, hackathon.name) break except Exception as e: self.log.error(e) self.log.error("check default experiment failed")
def get_online_hackathons(self): return Hackathon.objects(status=HACK_STATUS.ONLINE)
def get_hackathon_notice_list(self, body): """ list hackathon notices, notices are paginated, can be filtered by hackathon_name, event and category, can be ordered by update_time, event and category. :type body: Context :param body: valid key/values(all key/values are optional) body = { hackathon_name: string, // filter by hackathon_name, default unfiltered filter_by_user: '******' | 'all', // filter by user, default filter all notice that has specfic receivers category: 'int[,int...]', // filter by category, default unfiltered event: 'int[,int...]', // filter by event, default unfiltered order_by: 'time' | 'event' | 'category', // order by update_time, event, category, default by time page: int, // page number after pagination, start from 1, default 1 per_page: int // items per page, default 1000 } :return: json style text, see util.Utility ::Example: : body = { order_by: 'time', category: '1,2,3', page: 1, per_page: 6 } search first 6 notices ordered by time, filtered by: category in [1,2,3] : body = { hackathon_name: 'hackathon', event: '1', order_by: 'event' } search first 1000 notices ordered by event, filtered by event == 1 and hackathon_name == 'hackathon' """ hackathon_name = body.get("hackathon_name") filter_by_user = body.get("filter_by_user", "") notice_category = body.get("category") notice_event = body.get("event") order_by = body.get("order_by", "time") page = int(body.get("page", 1)) per_page = int(body.get("per_page", 1000)) hackathon_filter = Q() category_filter = Q() event_filter = Q() user_filter = Q(receiver=None) is_read_filter = Q() order_by_condition = '-update_time' if hackathon_name: #list notices that belong to specfic hackathon hackathon = Hackathon.objects( name=hackathon_name).only('name').first() if hackathon: hackathon_filter = Q(hackathon=hackathon) else: return not_found('hackathon_name not found') else: #only list online hackathons' notices or notices that not belong to any hackathon online_hackathon = Hackathon.objects(status=HACK_STATUS.ONLINE) hackathon_filter = Q(hackathon__in=online_hackathon) | Q( hackathon=None) if filter_by_user: # only return notices that are sent to the login user user = None if self.user_manager.validate_login(): user = g.user user_filter = Q(receiver=user) if filter_by_user == 'unread': is_read_filter = Q(is_read=False) else: return bad_request("please login first") if notice_category: notice_category_tuple = tuple( [int(category) for category in notice_category.split(',')]) category_filter = Q(category__in=notice_category_tuple) if notice_event: notice_event_tuple = tuple( [int(event) for event in notice_event.split(',')]) event_filter = Q(event__in=notice_event_tuple) if order_by == 'category': order_by_condition = '+category' elif order_by == 'event': order_by_condition = '+event' else: order_by_condition = '-update_time' pagination = HackathonNotice.objects( hackathon_filter & category_filter & event_filter & user_filter & is_read_filter).order_by(order_by_condition).paginate( page, per_page) def func(hackathon_notice): return hackathon_notice.dic() # return serializable items as well as total count return self.util.paginate(pagination, func)
def get_recyclable_hackathon_list(self): # todo filter hackathons in a db-level hackathons = Hackathon.objects().all() return filter(lambda h: self.is_recycle_enabled(h), hackathons)
def get_hackathon_notice_list(self, body): """ list hackathon notices, notices are paginated, can be filtered by hackathon_name, event and category, can be ordered by update_time, event and category. :type body: Context :param body: valid key/values(all key/values are optional) body = { hackathon_name: string, // filter by hackathon_name, default unfiltered filter_by_user: '******' | 'all', // filter by user, default filter all notice that has specfic receivers category: 'int[,int...]', // filter by category, default unfiltered event: 'int[,int...]', // filter by event, default unfiltered order_by: 'time' | 'event' | 'category', // order by update_time, event, category, default by time page: int, // page number after pagination, start from 1, default 1 per_page: int // items per page, default 1000 } :return: json style text, see util.Utility ::Example: : body = { order_by: 'time', category: '1,2,3', page: 1, per_page: 6 } search first 6 notices ordered by time, filtered by: category in [1,2,3] : body = { hackathon_name: 'hackathon', event: '1', order_by: 'event' } search first 1000 notices ordered by event, filtered by event == 1 and hackathon_name == 'hackathon' """ hackathon_name = body.get("hackathon_name") filter_by_user = body.get("filter_by_user", "") notice_category = body.get("category") notice_event = body.get("event") order_by = body.get("order_by", "time") page = int(body.get("page", 1)) per_page = int(body.get("per_page", 1000)) hackathon_filter = Q() category_filter = Q() event_filter = Q() user_filter = Q(receiver=None) is_read_filter = Q() order_by_condition = '-update_time' if hackathon_name: #list notices that belong to specfic hackathon hackathon = Hackathon.objects(name=hackathon_name).only('name').first() if hackathon: hackathon_filter = Q(hackathon=hackathon) else: return not_found('hackathon_name not found') else: #only list online hackathons' notices or notices that not belong to any hackathon online_hackathon = Hackathon.objects(status=HACK_STATUS.ONLINE) hackathon_filter = Q(hackathon__in=online_hackathon) | Q(hackathon=None) if filter_by_user: # only return notices that are sent to the login user user = None if self.user_manager.validate_login(): user = g.user user_filter = Q(receiver=user) if filter_by_user == 'unread': is_read_filter = Q(is_read=False) else: return bad_request("please login first") if notice_category: notice_category_tuple = tuple([int(category) for category in notice_category.split(',')]) category_filter = Q(category__in=notice_category_tuple) if notice_event: notice_event_tuple = tuple([int(event) for event in notice_event.split(',')]) event_filter = Q(event__in=notice_event_tuple) if order_by == 'category': order_by_condition = '+category' elif order_by == 'event': order_by_condition = '+event' else: order_by_condition = '-update_time' pagination = HackathonNotice.objects( hackathon_filter & category_filter & event_filter & user_filter & is_read_filter ).order_by( order_by_condition ).paginate(page, per_page) def func(hackathon_notice): return hackathon_notice.dic() # return serializable items as well as total count return self.util.paginate(pagination, func)