def register_model(self, *fields, **kw): """Registers a single model for fulltext search. This basically creates a simple PonyWhoosh.Index for the model and calls self.register_index on it. Args: *fields: all the fields indexed from the model. **kw: The options for each field, sortedby, stored ... """ index = PonyWhooshIndex(pw=self) index._kw = kw index._fields = fields def inner(model): """This look for the types of each field registered in the index, whether if it is Numeric, datetime, boolean or just text. Args: model (PonyORM.Entity): A model defined on the database with PonyORM Returns: model (PonyORM.Entity): A model modified for handle the appropriate search methods. """ index._name = model._table_ if not index._name: index._name = model.__name__ self._entities[index._name] = model index._schema_attrs = {} index._primary_key_is_composite = model._pk_is_composite_ index._primary_key = [f.name for f in model._pk_attrs_] index._primary_key_type = 'list' type_attribute = {} for field in model._attrs_: if field.is_relation: continue assert hasattr(field, "name") and hasattr(field, "py_type") fname = field.name if hasattr(field.name, "__name__"): fname = field.name.__name__ stored = kw.get("stored", False) if fname in index._primary_key: kw["stored"] = True # we're not supporting this kind of data ftype = field.py_type.__name__ if ftype in ['date', 'datetime', 'datetime.date']: kw["stored"] = stored continue fwhoosh = fwhoosh = whoosh.fields.TEXT(**kw) if field == model._pk_: index._primary_key_type = ftype fwhoosh = whoosh.fields.ID(stored=True, unique=True) if fname in index._fields: if not field.is_string: if ftype in ['int', 'float']: fwhoosh = whoosh.fields.NUMERIC(**kw) elif ftype == 'bool': fwhoosh = whoosh.fields.BOOLEAN(stored=True) type_attribute[fname] = ftype index._schema_attrs[fname] = fwhoosh kw["stored"] = stored index._schema = whoosh.fields.Schema(**index._schema_attrs) self.register_index(index) def _middle_save_(obj, status): """A middle-in-middle method to intercept CRUD operations from PonyORM over the current object model to update the appropriate whoosh index. Args: obj (EntityInstance): An instance of a current model. status (str): Type of transaction on the database. A CRUD operation. Returns: obj (EntityInstance): The same object as the input. """ writer = index._whoosh.writer(timeout=self.writer_timeout) dict_obj = obj.to_dict() def dumps(v): if isinstance(v, int): return unicode(v) if isinstance(v, float): return '%.9f' % v return unicode(v) attrs = {} for k, v in dict_obj.iteritems(): if k in index._schema_attrs.keys(): attrs[k] = dumps(v) if status == 'inserted': writer.add_document(**attrs) elif status == 'updated': writer.update_document(**attrs) elif status in set(['marked_to_delete', 'deleted', 'cancelled']): writer.delete_by_term(primary, attrs[primary]) writer.commit() return obj._after_save_ index._model = model model._after_save_ = _middle_save_ model._pw_index_ = index model.search = model._pw_index_.search return model return inner