class PidLog(db.Model): """ Audit log of actions happening to persistent identifiers. This model is primarily used through PersistentIdentifier.log and rarely created manually. """ __tablename__ = 'pidLOG' __table_args__ = (db.Index('idx_action', 'action'), ) id = db.Column(db.Integer(15, unsigned=True), primary_key=True) """ Id of persistent identifier entry """ id_pid = db.Column( db.Integer(15, unsigned=True), db.ForeignKey(PersistentIdentifier.id), nullable=True, ) """ PID """ timestamp = db.Column(db.DateTime(), nullable=False, default=datetime.now) """ Creation datetime of entry """ action = db.Column(db.String(10), nullable=False) """ Action identifier """ message = db.Column(db.Text(), nullable=False) """ Log message """
class WebQuery(db.Model): """Represents a WebQuery record.""" __tablename__ = 'query' id = db.Column(db.Integer(15, unsigned=True), primary_key=True, autoincrement=True) type = db.Column(db.Char(1), nullable=False, server_default='r') urlargs = db.Column(db.Text(100), nullable=False, index=True)
def do_upgrade(): """ Implement your upgrades here """ m = db.MetaData(bind=db.engine) m.reflect() t = db.Table( 'userCOLLECTION', m, db.Column('id', db.String(length=100), primary_key=True, nullable=False), db.Column('id_user', db.Integer(15, unsigned=True), db.ForeignKey('user.id'), nullable=False), db.Column('id_collection', db.MediumInteger(9, unsigned=True), db.ForeignKey('collection.id'), nullable=True), db.Column('id_collection_provisional', db.MediumInteger(9, unsigned=True), db.ForeignKey('collection.id'), nullable=True), db.Column('id_oairepository', db.MediumInteger(9, unsigned=True), db.ForeignKey('oaiREPOSITORY.id'), nullable=True), db.Column('title', db.String(length=255), nullable=False), db.Column('description', db.Text(), nullable=False), db.Column('page', db.Text(), nullable=False), db.Column('curation_policy', db.Text(), nullable=False), db.Column('has_logo', db.Boolean(), nullable=False), db.Column('created', db.DateTime(), nullable=False), db.Column('last_modified', db.DateTime(), nullable=False), mysql_engine='MyISAM', ) t.create()
class KnwKBRVAL(db.Model): """Represents a KnwKBRVAL record.""" def __init__(self): pass __tablename__ = 'knwKBRVAL' id = db.Column(db.MediumInteger(8, unsigned=True), nullable=False, primary_key=True, autoincrement=True) m_key = db.Column(db.String(255), nullable=False, server_default='', index=True) m_value = db.Column(db.Text(30), nullable=False, index=True) id_knwKB = db.Column(db.MediumInteger(8), db.ForeignKey(KnwKB.id), nullable=False, server_default='0') kb = db.relationship(KnwKB, backref='kbrvals')
class UserCollection(db.Model): """ Represents a user collection - a layer around Invenio's collections and portalboxes, that allow end-users to create """ __tablename__ = 'userCOLLECTION' # # Fields # id = db.Column(db.String(100), primary_key=True) """ User collection identifier used to generate the real collection_identifier """ id_user = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=False) """ Owner of the collection. """ id_collection = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(Collection.id), nullable=True, default=None) """ Invenio collection generated from this collection """ id_collection_provisional = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(Collection.id), nullable=True, default=None) """ Invenio provisional collection generated from this collection """ id_oairepository = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(OaiREPOSITORY.id), nullable=True, default=None) """ OAI Repository set specification """ title = db.Column(db.String(length=255), nullable=False, default='') """ Title of collection. """ description = db.Column(db.Text(), nullable=False, default='') """ Short description of collection, displayed in portal boxes. """ page = db.Column(db.Text(), nullable=False, default='') """ Long description of collection, displayed on an individual page. """ curation_policy = db.Column(db.Text(), nullable=False, default='') """ """ has_logo = db.Column(db.Boolean(), nullable=False, default=False) """ """ created = db.Column(db.DateTime(), nullable=False, default=datetime.now) """ Creation datetime """ last_modified = db.Column(db.DateTime(), nullable=False, default=datetime.now, onupdate=datetime.now) """ Last modification datetime """ # # Relation ships # owner = db.relationship(User, backref='usercollections', foreign_keys=[id_user]) """ Relation to the owner (User) of the collection """ collection = db.relationship(Collection, uselist=False, backref='usercollection', foreign_keys=[id_collection]) """ Relationship to Invenio collection. """ collection_provisional = db.relationship( Collection, uselist=False, backref='usercollection_provisional', foreign_keys=[id_collection_provisional]) """ Relationship to Invenio restricted collection containing uncurated records. """ oai_set = db.relationship(OaiREPOSITORY, uselist=False, backref='usercollection', foreign_keys=[id_oairepository]) """ Relation to the owner (User) of the collection """ # # Properties # @property def logo_url(self): """ Get URL to collection logo """ # FIXME if self.has_logo: raise NotImplementedError else: return None @property def oai_url(self): """ Get link to OAI-PMH API for this user collection """ return "/oai2d?verb=ListRecords&metadataPrefix=oai_dc&set=%s" % self.get_collection_name( ) @property def collection_url(self): """ Get URL to collection """ return "/collection/%s" % self.get_collection_name() @property def collection_provisional_url(self): """ Get URL to provisional collection """ return "/search?cc=%s" % self.get_collection_name(provisional=True) @property def upload_url(self): """ Get direct upload URL """ return url_for('webdeposit.index', c=self.id) # # # @classmethod def from_recid(cls, recid, provisional=False): """ Get user collections specified in recid """ rec = get_record(recid) prefix = "%s-" % (CFG_USERCOLLECTION_ID_PREFIX_PROVISIONAL if provisional else CFG_USERCOLLECTION_ID_PREFIX) colls = rec.get('980', []) usercolls = [] for c in colls: try: # We are only interested in subfield 'a' code, val = c[0][0] if code == 'a' and val.startswith(prefix): val = val[len(prefix):] u = UserCollection.query.filter_by(id=val).first() if u: usercolls.append(u) except IndexError: pass return usercolls # # Utility methods # def get_collection_name(self, provisional=False): """ Get a unique collection name identifier """ if provisional: return "%s-%s" % (CFG_USERCOLLECTION_ID_PREFIX_PROVISIONAL, self.id) else: return "%s-%s" % (CFG_USERCOLLECTION_ID_PREFIX, self.id) def get_title(self, provisional=False): if provisional: return "Provisional: %s" % self.title else: return self.title def get_collection_dbquery(self, provisional=False): """ Get collection query """ return "%s:%s" % self.get_query(provisional=provisional) def get_query(self, provisional=False): """ Get tuple (field,value) for search engine query """ return ("980__a", self.get_collection_name(provisional=provisional)) def render_portalbox_bodies(self, templates): """ Get a list of rendered portal boxes for this user collection """ ctx = { 'usercollection': self, } return map(lambda t: render_template_to_string(t, **ctx), templates) # # Curation methods # def _modify_record(self, recid, test_func, replace_func, include_func, append_colls=[], replace_colls=[]): """ Generate record a MARCXML file @param test_func: Function to test if a collection id should be changed @param replace_func: Function to replace the collection id. @param include_func: Function to test if collection should be included """ rec = get_record(recid) newcolls = [] dirty = False try: colls = rec['980'] if replace_colls: for c in replace_colls: newcolls.append([('a', c)]) dirty = True else: for c in colls: try: # We are only interested in subfield 'a' code, val = c[0][0] if test_func(code, val): c[0][0] = replace_func(code, val) dirty = True if include_func(code, val): newcolls.append(c[0]) else: dirty = True except IndexError: pass for c in append_colls: newcolls.append([('a', c)]) dirty = True except KeyError: return False if not dirty: return False rec = {} record_add_field(rec, '001', controlfield_value=str(recid)) for subfields in newcolls: record_add_field(rec, '980', subfields=subfields) return rec def _upload_record(self, rec, pretend=False): """ Bibupload one record """ if rec is False: return None if not pretend: bibupload_record( record=rec, file_prefix='usercoll', mode='-c', opts=['-n', '-P5'], alias="usercoll", ) return rec def _upload_collection(self, coll): """ Bibupload many records """ bibupload_record( collection=coll, file_prefix='usercoll', mode='-c', opts=['-n', '-P5'], alias="usercoll", ) return True def accept_record(self, recid, pretend=False): """ Accept a record for inclusion in a user collection @param recid: Record ID """ expected_id = self.get_collection_name(provisional=True) new_id = self.get_collection_name(provisional=False) append_colls, replace_colls = signalresult2list( pre_curation.send(self, action='accept', recid=recid, pretend=pretend)) def test_func(code, val): return code == 'a' and val == expected_id def replace_func(code, val): return (code, new_id) def include_func(code, val): return True rec = self._upload_record(self._modify_record( recid, test_func, replace_func, include_func, append_colls=append_colls, replace_colls=replace_colls), pretend=pretend) post_curation.send(self, action='accept', recid=recid, record=rec, pretend=pretend) return rec def reject_record(self, recid, pretend=False): """ Reject a record for inclusion in a user collection @param recid: Record ID """ expected_id = self.get_collection_name(provisional=True) new_id = self.get_collection_name(provisional=False) append_colls, replace_colls = signalresult2list( pre_curation.send(self, action='reject', recid=recid, pretend=pretend)) def test_func(code, val): return False def replace_func(code, val): return (code, val) def include_func(code, val): return not (code == 'a' and (val == expected_id or val == new_id)) rec = self._upload_record(self._modify_record( recid, test_func, replace_func, include_func, append_colls=append_colls, replace_colls=replace_colls), pretend=pretend) post_curation.send(self, action='reject', recid=recid, record=rec, pretend=pretend) return rec # # Data persistence methods # def save_collectionname(self, collection, title): """ Create or update Collectionname object """ if collection.id: c_name = Collectionname.query.filter_by( id_collection=collection.id, ln=CFG_SITE_LANG, type='ln').first() if c_name: update_changed_fields(c_name, dict(value=title)) return c_name c_name = Collectionname( collection=collection, ln=CFG_SITE_LANG, type='ln', value=title, ) db.session.add(c_name) return c_name def save_collectiondetailedrecordpagetabs(self, collection): """ Create or update Collectiondetailedrecordpagetabs object """ if collection.id: c_tabs = Collectiondetailedrecordpagetabs.query.filter_by( id_collection=collection.id).first() if c_tabs: update_changed_fields(c_tabs, dict(tabs=CFG_USERCOLLCTION_TABS)) return c_tabs c_tabs = Collectiondetailedrecordpagetabs( collection=collection, tabs=CFG_USERCOLLCTION_TABS, ) db.session.add(c_tabs) return c_tabs def save_collectioncollection(self, collection, parent_name): """ Create or update CollectionCollection object """ dad = Collection.query.filter_by(name=parent_name).first() if collection.id: c_tree = CollectionCollection.query.filter_by( id_dad=dad.id, id_son=collection.id).first() if c_tree: update_changed_fields( c_tree, dict(type=CFG_USERCOLLECTION_COLLECTION_TYPE, score=CFG_USERCOLLECTION_COLLECTION_SCORE)) return c_tree c_tree = CollectionCollection( dad=dad, son=collection, type=CFG_USERCOLLECTION_COLLECTION_TYPE, score=CFG_USERCOLLECTION_COLLECTION_SCORE, ) db.session.add(c_tree) return c_tree def save_collectionformat(self, collection, fmt_str): """ Create or update CollectionFormat object """ fmt = Format.query.filter_by(code=fmt_str).first() if collection.id: c_fmt = CollectionFormat.query.filter_by( id_collection=collection.id).first() if c_fmt: update_changed_fields(c_fmt, dict(id_format=fmt.id, score=1)) return c_fmt c_fmt = CollectionFormat( collection=collection, format=fmt, ) db.session.add(c_fmt) return c_fmt def save_collectionportalboxes(self, collection, templates): """ Create or update Portalbox and CollectionPortalbox objects """ # Setup portal boxes bodies = self.render_portalbox_bodies(templates) bodies.reverse() # Highest score is on the top, so we reverse the list objects = [] if collection.id: c_pboxes = CollectionPortalbox.query.filter_by( id_collection=collection.id, ln=CFG_SITE_LANG, ).all() if len(c_pboxes) == len(bodies): for score, elem in enumerate(zip(c_pboxes, bodies)): c_pbox, body = elem pbox = c_pbox.portalbox update_changed_fields(pbox, dict(body=body)) update_changed_fields( c_pbox, dict(score=score, position=CFG_USERCOLLECTION_PORTALBOX_POSITION)) objects.append(c_pbox) return objects else: # Either templates where modified or collection portalboxes # where modified outside of the UserCollection. In either case, # remove existing portalboxes and add new ones. for c_pbox in c_pboxes: db.session.delete(c_pbox.portalbox) db.session.delete(c_pbox) for score, body in enumerate(bodies): p = Portalbox(title='', body=body) c_pbox = CollectionPortalbox() update_changed_fields( c_pbox, dict( collection=collection, portalbox=p, ln=CFG_SITE_LANG, position=CFG_USERCOLLECTION_PORTALBOX_POSITION, score=score, )) db.session.add_all([p, c_pbox]) objects.append(c_pbox) return objects def save_oairepository_set(self, provisional=False): """ Create or update OAI Repository set. """ collection_name = self.get_collection_name(provisional=provisional) (f1, p1) = self.get_query(provisional=provisional) fields = dict( setName='%s set' % collection_name, setSpec=collection_name, setDescription=self.description, p1=p1, f1=f1, m1='e', p2='', f2='', m2='', p3='', f3='', m3='', ) if self.oai_set: update_changed_fields(self.oai_set, fields) else: self.oai_set = OaiREPOSITORY(**fields) db.session.add(self.oai_set) def save_acl(self, collection_id, collection_name): """ Create or update authorization for user to view the provisional collection """ # Role - use collection id, because role name is limited to 32 chars. role_name = 'coll_%s' % collection_id role = AccROLE.query.filter_by(name=role_name).first() if not role: role = AccROLE(name=role_name, description='Curators of collection %s' % collection_name) db.session.add(role) # Argument fields = dict(keyword='collection', value=collection_name) arg = AccARGUMENT.query.filter_by(**fields).first() if not arg: arg = AccARGUMENT(**fields) db.session.add(arg) # Action action = AccACTION.query.filter_by(name='viewrestrcoll').first() # User role alluserroles = UserAccROLE.query.filter_by(role=role).all() userrole = None if alluserroles: # Remove any user which is not the owner for ur in alluserroles: if ur.id_user == self.id_user: db.session.delete(ur) else: userrole = ur if not userrole: userrole = UserAccROLE(user=self.owner, role=role) db.session.add(userrole) # Authorization auth = AccAuthorization.query.filter_by(role=role, action=action, argument=arg).first() if not auth: auth = AccAuthorization(role=role, action=action, argument=arg, argumentlistid=1) def save_collection(self, provisional=False): """ Create or update a new collection with name, tabs, collection tree, collection output formats, portalboxes and OAI repository set """ # Setup collection collection_name = self.get_collection_name(provisional=provisional) c = Collection.query.filter_by(name=collection_name).first() fields = dict( name=collection_name, dbquery=self.get_collection_dbquery(provisional=provisional)) if c: before_save_collection.send(self, is_new=True, provisional=provisional) update_changed_fields(c, fields) else: before_save_collection.send(self, is_new=False, provisional=provisional) c = Collection(**fields) db.session.add(c) db.session.commit() setattr(self, 'collection_provisional' if provisional else 'collection', c) # Setup OAI Repository if provisional: self.save_acl(c.id, collection_name) else: self.save_oairepository_set(provisional=provisional) # Setup title, tabs and collection tree self.save_collectionname(c, self.get_title(provisional=provisional)) self.save_collectiondetailedrecordpagetabs(c) self.save_collectioncollection( c, CFG_USERCOLLCTION_PARENT_NAME_PROVISIONAL if provisional else CFG_USERCOLLCTION_PARENT_NAME) # Setup collection format is needed if not provisional and CFG_USERCOLLCTION_OUTPUTFORMAT: self.save_collectionformat(c, CFG_USERCOLLCTION_OUTPUTFORMAT) elif provisional and CFG_USERCOLLCTION_OUTPUTFORMAT_PROVISIONAL: self.save_collectionformat( c, CFG_USERCOLLCTION_OUTPUTFORMAT_PROVISIONAL) # Setup portal boxes self.save_collectionportalboxes( c, CFG_USERCOLLCTION_PORTALBOXES_PROVISIONAL if provisional else CFG_USERCOLLCTION_PORTALBOXES) db.session.commit() after_save_collection.send(self, collection=c, provisional=provisional) def save_collections(self): """ Create restricted and unrestricted collection """ before_save_collections.send(self) self.save_collection(provisional=False) self.save_collection(provisional=True) after_save_collections.send(self) def delete_record_collection_identifiers(self): """ Remove collection identifiers for this user collection from all records. """ provisional_id = self.get_collection_name(provisional=True) normal_id = self.get_collection_name(provisional=False) def test_func(code, val): return False def replace_func(code, val): return (code, val) def include_func(code, val): return not (code == 'a' and (val == provisional_id or val == normal_id)) coll = [] for r in search_pattern(p="980__a:%s OR 980__a:%s" % (normal_id, provisional_id)): coll.append( self._modify_record(r, test_func, replace_func, include_func)) self._upload_collection(coll) def delete_collection(self, provisional=False): """ Delete all objects related to a single collection """ # Most of the logic in this method ought to be moved to a # Collection.delete() method. c = getattr(self, "collection_provisional" if provisional else "collection") collction_name = self.get_collection_name(provisional=provisional) before_delete_collection.send(self, collection=c, provisional=provisional) if c: # Delete portal boxes for c_pbox in c.portalboxes: if c_pbox.portalbox: db.session.delete(c_pbox.portalbox) db.session.delete(c_pbox) # Delete output formats: CollectionFormat.query.filter_by(id_collection=c.id).delete() # Delete title, tabs, collection tree Collectionname.query.filter_by(id_collection=c.id).delete() CollectionCollection.query.filter_by(id_son=c.id).delete() Collectiondetailedrecordpagetabs.query.filter_by( id_collection=c.id).delete() if provisional: # Delete ACLs AccARGUMENT.query.filter_by(keyword='collection', value=collction_name).delete() role = AccROLE.query.filter_by(name='coll_%s' % c.id).first() if role: UserAccROLE.query.filter_by(role=role).delete() AccAuthorization.query.filter_by(role=role).delete() db.session.delete(role) else: # Delete OAI repository if self.oai_set: db.session.delete(self.oai_set) # Delete collection if c: db.session.delete(c) db.session.commit() after_delete_collection.send(self, provisional=provisional) def delete_collections(self): """ Delete collection and all associated objects. """ before_delete_collections.send(self) self.delete_record_collection_identifiers() self.delete_collection(provisional=False) self.delete_collection(provisional=True) after_delete_collections.send(self)
class Collection(db.Model): """Represents a Collection record.""" def __repr__(self): return "%s(%s)" % (self.__class__.__name__, self.id) __tablename__ = 'collection' id = db.Column(db.MediumInteger(9, unsigned=True), primary_key=True) name = db.Column(db.String(255), unique=True, index=True, nullable=False) dbquery = db.Column(db.Text(20), nullable=True, index=True) nbrecs = db.Column(db.Integer(10, unsigned=True), server_default='0') #FIXME read only!!! reclist = db.Column( db.PickleType(pickler=IntbitsetPickle(), comparator=IntbitsetCmp)) _names = db.relationship( lambda: Collectionname, backref='collection', collection_class=attribute_mapped_collection('ln_type'), cascade="all, delete, delete-orphan") names = association_proxy( '_names', 'value', creator=lambda k, v: Collectionname(ln_type=k, value=v)) _formatoptions = association_proxy('formats', 'format') #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def formatoptions(self): if len(self._formatoptions): return [dict(f) for f in self._formatoptions] else: return [{ 'code': 'hb', 'name': "HTML %s" % g._("brief"), 'content_type': 'text/html' }] formatoptions = property(formatoptions) _examples_example = association_proxy('_examples', 'example') @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def examples(self): return list(self._examples_example) @property def name_ln(self): from invenio.search_engine import get_coll_i18nname return get_coll_i18nname(self.name, g.ln).decode('utf-8') # Another possible implementation with cache memoize # @cache.memoize #try: # return db.object_session(self).query(Collectionname).\ # with_parent(self).filter(db.and_(Collectionname.ln==g.ln, # Collectionname.type=='ln')).first().value #except: # return self.name @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def portalboxes_ln(self): return db.object_session(self).query(CollectionPortalbox).\ with_parent(self).\ options(db.joinedload_all(CollectionPortalbox.portalbox)).\ filter(CollectionPortalbox.ln == g.ln).\ order_by(db.desc(CollectionPortalbox.score)).all() @property def most_specific_dad(self): return db.object_session(self).query(Collection).\ join(Collection.sons).\ filter(CollectionCollection.id_son == self.id).\ order_by(db.asc(Collection.nbrecs)).\ first() @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def is_restricted(self): from invenio.search_engine import collection_restricted_p return collection_restricted_p(self.name) @property def type(self): p = re.compile("\d+:.*") if self.dbquery is not None and \ p.match(self.dbquery.lower()): return 'r' else: return 'v' _collection_children = db.relationship( lambda: CollectionCollection, #collection_class=OrderedList, collection_class=ordering_list('score'), primaryjoin=lambda: Collection.id == CollectionCollection.id_dad, foreign_keys=lambda: CollectionCollection.id_dad, order_by=lambda: db.asc(CollectionCollection.score)) _collection_children_r = db.relationship( lambda: CollectionCollection, #collection_class=OrderedList, collection_class=ordering_list('score'), primaryjoin=lambda: db.and_( Collection.id == CollectionCollection.id_dad, CollectionCollection. type == 'r'), foreign_keys=lambda: CollectionCollection.id_dad, order_by=lambda: db.asc(CollectionCollection.score)) _collection_children_v = db.relationship( lambda: CollectionCollection, #collection_class=OrderedList, collection_class=ordering_list('score'), primaryjoin=lambda: db.and_( Collection.id == CollectionCollection.id_dad, CollectionCollection. type == 'v'), foreign_keys=lambda: CollectionCollection.id_dad, order_by=lambda: db.asc(CollectionCollection.score)) collection_parents = db.relationship( lambda: CollectionCollection, #collection_class=OrderedList, collection_class=ordering_list('score'), primaryjoin=lambda: Collection.id == CollectionCollection.id_son, foreign_keys=lambda: CollectionCollection.id_son, order_by=lambda: db.asc(CollectionCollection.score)) collection_children = association_proxy('_collection_children', 'son') collection_children_r = association_proxy( '_collection_children_r', 'son', creator=lambda son: CollectionCollection(id_son=son.id, type='r')) collection_children_v = association_proxy( '_collection_children_v', 'son', creator=lambda son: CollectionCollection(id_son=son.id, type='v')) # _externalcollections = db.relationship( lambda: CollectionExternalcollection, # backref='collection', cascade="all, delete, delete-orphan") # # externalcollections = association_proxy( # '_externalcollections', # 'externalcollection') def _externalcollections_type(type): return association_proxy( '_externalcollections_' + str(type), 'externalcollection', creator=lambda ext: CollectionExternalcollection( externalcollection=ext, type=type)) externalcollections_0 = _externalcollections_type(0) externalcollections_1 = _externalcollections_type(1) externalcollections_2 = _externalcollections_type(2) externalcollections = db.relationship( lambda: CollectionExternalcollection, #backref='collection', collection_class=external_collection_mapper, cascade="all, delete, delete-orphan") # Search options _make_field_fieldvalue = lambda type: db.relationship( lambda: CollectionFieldFieldvalue, primaryjoin=lambda: db.and_( Collection.id == CollectionFieldFieldvalue.id_collection, CollectionFieldFieldvalue.type == type), order_by=lambda: CollectionFieldFieldvalue.score) _search_within = _make_field_fieldvalue('sew') _search_options = _make_field_fieldvalue('seo') @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def search_within(self): """ Collect search within options. """ from invenio.search_engine_config import CFG_WEBSEARCH_SEARCH_WITHIN default = [('', g._('any field'))] found = [(o.field.code, o.field.name_ln) for o in self._search_within] if not found: found = [(f.name.replace(' ', ''), f.name_ln) for f in Field.query.filter( Field.name.in_(CFG_WEBSEARCH_SEARCH_WITHIN)).all()] return default + sorted(found, key=itemgetter(1)) @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def search_options(self): return self._search_options @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def ancestors_ids(self): """Get list of parent collection ids.""" output = intbitset([self.id]) for c in self.dads: ancestors = c.dad.ancestors_ids if self.id in ancestors: raise output |= ancestors return output @property #@cache.memoize(make_name=lambda fname: fname + '::' + g.ln) def descendants_ids(self): """Get list of child collection ids.""" output = intbitset([self.id]) for c in self.sons: descendants = c.son.descendants_ids if self.id in descendants: raise output |= descendants return output # Gets the list of localized names as an array collection_names = db.relationship( lambda: Collectionname, primaryjoin=lambda: Collection.id == Collectionname.id_collection, foreign_keys=lambda: Collectionname.id_collection) # Gets the translation according to the lang code def translation(self, lang): try: return db.object_session(self).query(Collectionname).\ with_parent(self).filter(db.and_(Collectionname.ln == lang, Collectionname.type == 'ln')).first().value except: return "" portal_boxes_ln = db.relationship( lambda: CollectionPortalbox, #collection_class=OrderedList, collection_class=ordering_list('score'), primaryjoin=lambda: \ Collection.id == CollectionPortalbox.id_collection, foreign_keys=lambda: CollectionPortalbox.id_collection, order_by=lambda: db.asc(CollectionPortalbox.score)) #@db.hybrid_property #def externalcollections(self): # return self._externalcollections #@externalcollections.setter #def externalcollections(self, data): # if isinstance(data, dict): # for k, vals in data.iteritems(): # for v in list(vals): # self._externalcollections[k] = v # else: # self._externalcollections = data def breadcrumbs(self, builder=None, ln=CFG_SITE_LANG): """Retunds breadcrumbs for collection.""" breadcrumbs = [] # Get breadcrumbs for most specific dad if it exists. if self.most_specific_dad is not None: breadcrumbs = self.most_specific_dad.breadcrumbs(builder=builder, ln=ln) if builder is not None: crumb = builder(self) else: crumb = (self.name_ln, 'search.collection', dict(name=self.name)) breadcrumbs.append(crumb) return breadcrumbs