使用方法作为__searchable__ in flask-whooshalchemy

时间:2014-01-05 20:14:11

标签: python sqlalchemy flask whoosh

我有一个sqlalchemy模型,我正在搜索flask-whooshalchemy。我希望在搜索字段中包含方法的输出,但无法弄清楚它是如何完成的,或者它是否可能。烧瓶 - whooshalchemy文件有点限制。

我正在尝试这样的事情:

class Trade(db.Model):
    __searchable__ = [
        'species', 'nature', 'ability', 'move1', 'move2', 'move3', 'move4', 'ivSpread']

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    dex_no = db.Column(db.Integer)
    species = db.Column(db.String(30))
    male = db.Column(db.Boolean)
    female = db.Column(db.Boolean)
    nature = db.Column(db.String(30))
    ability = db.Column(db.String(30))
    iv_hp = db.Column(db.Integer)
    iv_atk = db.Column(db.Integer)
    iv_def = db.Column(db.Integer)
    iv_spa = db.Column(db.Integer)
    iv_spd = db.Column(db.Integer)
    iv_spe = db.Column(db.Integer)
    move1 = db.Column(db.String(30))
    move2 = db.Column(db.String(30))
    move3 = db.Column(db.String(30))
    move4 = db.Column(db.String(30))

    def ivSpread(self):
        ivs = [
            self.iv_hp,
            self.iv_atk,
            self.iv_def,
            self.iv_spa,
            self.iv_spd,
            self.iv_spe
        ]
        return "/".join(ivs)

    def __repr__(self):
        return '<Post %r: %r>' % (self.owner.nickname, self.species)

如果我能提供更多信息,请与我们联系。关于使用备用模块的建议也很好,我相信可能会有更强大的东西,而不是烧瓶 - whooshalchemy。毕竟,它在两年内还没有被推到。

e:使用上面的原样和下面Mark Hildreth提供的@property建议,我得到以下追溯。

whoosh.fields.UnknownFieldError
UnknownFieldError: No field named 'ivSpread' in <Schema: ['ability', 'gender', 'id', 'move1', 'move2', 'move3', 'move4', 'nature', 'species']>

Traceback (most recent call last):
  File "c:\Python27\lib\site-packages\flask\app.py", line 1701, in __call__
    return self.wsgi_app(environ, start_response)
  File "c:\Python27\lib\site-packages\flask\app.py", line 1689, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "c:\Python27\lib\site-packages\flask\app.py", line 1687, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\Python27\lib\site-packages\flask\app.py", line 1360, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\Python27\lib\site-packages\flask\app.py", line 1358, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\Python27\lib\site-packages\flask\app.py", line 1344, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "c:\Users\Shane\Documents\Coding\python\flask\trade_lister\app\views.py", line 172, in new_trade
    db.session.commit()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\scoping.py", line 114, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 703, in commit
    self.transaction.commit()
  File "c:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 367, in commit
    self.session.dispatch.after_commit(self.session)
  File "c:\Python27\lib\site-packages\sqlalchemy\event.py", line 319, in __call__
    fn(*args, **kw)
  File "c:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py", line 170, in session_signal_after_commit
    models_committed.send(session.app, changes=d.values())
  File "c:\Python27\lib\site-packages\blinker\base.py", line 267, in send
    for receiver in self.receivers_for(sender)]
  File "c:\Python27\lib\site-packages\flask_whooshalchemy.py", line 256, in _after_flush
    writer.update_document(**attrs)
  File "c:\Python27\lib\site-packages\whoosh\writing.py", line 477, in update_document
    self.add_document(**fields)
  File "c:\Python27\lib\site-packages\whoosh\writing.py", line 730, in add_document
    self._check_fields(schema, fieldnames)
  File "c:\Python27\lib\site-packages\whoosh\writing.py", line 718, in _check_fields
    % (name, schema))
UnknownFieldError: No field named 'ivSpread' in <Schema: ['ability', 'gender', 'id', 'move1', 'move2', 'move3', 'move4', 'nature', 'species']>

1 个答案:

答案 0 :(得分:1)

我不太了解Woosh或Flask-Wooshalchemy,所以这可能是错的,但我想你可能能够做这样的事情......

class Trade(db.Model):
    #...

    @property
    def ivSpread(self):
        #...

这使用property使方法调用看起来像一个属性,所以不要......     贸易(...)     print t.ivSpread()

......你会做......

t = Trade(...)
print t.ivSpread

这是必要的,因为Flask-WooshAlchemy似乎假设可搜索的项目是一个属性,此时它只是在不调用它的情况下拉动方法。

如果你需要让ivSpread保留一个方法,你可以使用包装器:

class Trade(db.Model):
    #...

    def ivSpread(self):
        #...

    @property
    def ivSpreadProp(self):
        return self.ivSpread()

然后你需要ivSpreadProp搜索ivSpread rthan。

修改

看起来你正在尝试做的事情目前无法实现。见here

searchable = set(model.__searchable__)
for field in model.__table__.columns:
    if field.primary_key:
        schema[field.name] = whoosh.fields.ID(stored=True, unique=True)
        primary = field.name

    if field.name in searchable and isinstance(field.type,
            (sqlalchemy.types.Text, sqlalchemy.types.String,
                sqlalchemy.types.Unicode)):

        schema[field.name] = whoosh.fields.TEXT(
                analyzer=StemmingAnalyzer())

Flask-WhooshAlchemy假定__searchable__属性中的项目将是您的模型使用SQLAlchemy定义的列。 Flask-WhooshAlchemy需要让你干净利落地实现你的目标。