Simon Brix
Simon Brix

Reputation: 102

Peewee throws KeyError when trying to add user defined operator

I followed the short guide in the peewee docs on how to add user defined operators, but when I try to do it, it gives me a KeyError.

from peewee import *
from peewee import OP
from peewee import Expression

db = MySQLDatabase(app.config['MYSQL_DATABASE_DB'], host=app.config['MYSQL_DATABASE_HOST'], user=app.config['MYSQL_DATABASE_USER'], passwd=app.config['MYSQL_DATABASE_PASSWORD'])

OP['MOD'] = 'mod'

def mod(lhs, rhs):
    return Expression(lhs, OP.MOD, rhs)

MySQLDatabase.register_ops({OP.MOD: '%'})

class Base(Model):
    class Meta:
        database = db

class User(Base):
    user_id = PrimaryKeyField()
    first_name = CharField(max_length = 150)
    last_name = CharField(max_length = 150)

@app.route('/')
def test():
    query = User.select().where(mod(User.user_id, 2) == 0)
    return "Query: %r" % query

When I try to run it, it gives me this error:

KeyError: 'mod'

Any ideas what I might be doing wrong?

Upvotes: 0

Views: 633

Answers (3)

Fenghe Xu
Fenghe Xu

Reputation: 181

OP['MOD'] = 'mod'

def mod(lhs, rhs):
    return Expression(lhs, OP.MOD, rhs)

db = MySQLDatabase(
    app.config['MYSQL_DATABASE_DB'], 
    host=app.config['MYSQL_DATABASE_HOST'], 
    user=app.config['MYSQL_DATABASE_USER'], 
    passwd=app.config['MYSQL_DATABASE_PASSWORD'])

Specifying the ops argument will lead to error, in fact, you don't have to do that.

The only thing you have to be careful is to import the function mod you defined to the module that you want to use it in.

Upvotes: 0

coleifer
coleifer

Reputation: 26245

The problem is that you are defining your database before you are calling register_ops(). To fix the immediate bug you can move your db = MySQL... below the call to register_ops().

This does seem a little like a bug in peewee, though, so I've opened a github issue: https://github.com/coleifer/peewee/issues/599


Edit: I decided to after all not change the behavior. The solution I proposed should work, though -- register ops first, instantiate second. You can also specify custom ops when instantiating the database:

http://docs.peewee-orm.com/en/latest/peewee/api.html#Database

Example

OP['MOD'] = 'mod'

def mod(lhs, rhs):
    return Expression(lhs, OP.MOD, rhs)

db = MySQLDatabase(
    app.config['MYSQL_DATABASE_DB'], 
    host=app.config['MYSQL_DATABASE_HOST'], 
    user=app.config['MYSQL_DATABASE_USER'], 
    passwd=app.config['MYSQL_DATABASE_PASSWORD'],
    ops={OP.MOD: '%'})

Upvotes: 1

Bidhan
Bidhan

Reputation: 10687

Before this

def mod(lhs, rhs):
    return Expression(lhs, OP.MOD, rhs)

You need to define this

OP['MOD'] = 'mod'

Upvotes: 0

Related Questions