Python: Generic/Templated 吸气剂
Python: Generic/Templated getters
我有一个代码可以简单地从数据库中获取 user/s
class users:
def __init__(self):
self.engine = create_engine("mysql+pymysql://root:password@127.0.0.1/my_database")
self.connection = self.engine.connect()
self.meta = MetaData(bind=self.connection)
self.users = Table('users', self.meta, autoload = true)
def get_user_by_user_id(self, user_id):
stmt = self.users.select().where(self.users.c.user_id == user_id)
return self.connection.execute(stmt)
def get_user_by_username(self, username):
stmt = self.users.select().where(self.users.c.username == username)
return self.connection.execute(stmt)
def get_users_by_role_and_company(self, role, company)
stmt = self.users.select().where(self.users.c.role == role).where(self.users.c.company == company)
return self.connection.execute(stmt)
现在,我想做的是像这样使 getter 通用:
class users:
def __init__(self):
self.engine = create_engine("mysql+pymysql://root:password@127.0.0.1/my_database")
self.connection = self.engine.connect()
self.meta = MetaData(bind=self.connection)
self.users = Table('users', self.meta, autoload = true)
def get_user(self, **kwargs):
'''How do I make this generic function?'''
所以,不要像这样调用:
u = users()
u.get_user_by_user_id(1)
u.get_user_by_username('foo')
u.get_users_by_role_and_company('Admin', 'bar')
我会像这样调用通用函数:
u = users()
u.get_user(user_id=1)
u.get_user(username='foo')
u.get_user(role='Admin', company='bar')
到目前为止,这是我能想到的:
def get_user(**kwargs):
where_clause = ''
for key, value in kwargs.items():
where_clause += '{} == {} AND '.format(key, value)
where_clause = where_clause[:-5] # remove final AND
stmt = "SELECT * FROM {tablename} WHERE {where_clause};".format(tablename='users', where_clause=where_clause)
return self.connection.execute(stmt)
有什么方法可以使用 ORM 样式来创建语句吗?
但您已经完成了所有艰苦的工作。这只是组合您创建的函数、初始化输入变量并在其中加入一些 if
语句的问题。
def get_user(self, user_id=0, username='', role='', company=''):
if user_id:
stmt = self.users.select().where(self.users.c.user_id == user_id)
return self.connection.execute(stmt)
elif username:
stmt = self.users.select().where(self.users.c.username == username)
return self.connection.execute(stmt)
elif role and company:
stmt = self.users.select().where(self.users.c.role == role).where(self.users.c.company == company)
return self.connection.execute(stmt)
else:
print('Not adequate information given. Please enter "ID" or "USERNAME", or "ROLE"&"COMPANY"')
return
请注意,user_id
已被初始化为 0
,因此它的布尔值是 False
。如果 0 id 是可能的,请将其直接设置为 False
。因此,由于输入不能是 'random',您是否有理由要使用 **kwargs
?
或者,如果组合的数量太多而无法编码,我会走不同的路线(SQL-injection-valnurable 脚本传入!)如下:
def get_user(self, query):
form_query = 'SELECT user FROM {} WHERE {}'.format(table_name, query)
# now execute it and return whatever it is you want returned
您不再将变量传递给函数,而是将字符串附加到查询并执行。
不用说,你必须非常小心。
试试这样的东西:
def get_user(self, **kwargs):
if 'user_id' in kwargs:
(...)
elif 'username' in kwargs:
(...)
elif all(a in ['role','company'] for a in kwargs):
(...)
else:
(...)
完全通用化,因此只要 table 中存在具有该名称的字段,任何合法字段名称的组合都可以接受。神奇之处在于 getattr
,它允许我们动态查找我们感兴趣的字段(如果使用不存在的字段名称调用则引发 AttributeError
):
def get_user(self, **kwargs):
# Basic query
stmt = self.users.select()
# Query objects can be refined piecemeal, so we just loop and
# add new clauses, assigning back to stmt to build up the query
for field, value in kwargs.items():
stmt = stmt.where(getattr(self.users.c, field) == value)
return self.connection.execute(stmt)
我有一个代码可以简单地从数据库中获取 user/s
class users:
def __init__(self):
self.engine = create_engine("mysql+pymysql://root:password@127.0.0.1/my_database")
self.connection = self.engine.connect()
self.meta = MetaData(bind=self.connection)
self.users = Table('users', self.meta, autoload = true)
def get_user_by_user_id(self, user_id):
stmt = self.users.select().where(self.users.c.user_id == user_id)
return self.connection.execute(stmt)
def get_user_by_username(self, username):
stmt = self.users.select().where(self.users.c.username == username)
return self.connection.execute(stmt)
def get_users_by_role_and_company(self, role, company)
stmt = self.users.select().where(self.users.c.role == role).where(self.users.c.company == company)
return self.connection.execute(stmt)
现在,我想做的是像这样使 getter 通用:
class users:
def __init__(self):
self.engine = create_engine("mysql+pymysql://root:password@127.0.0.1/my_database")
self.connection = self.engine.connect()
self.meta = MetaData(bind=self.connection)
self.users = Table('users', self.meta, autoload = true)
def get_user(self, **kwargs):
'''How do I make this generic function?'''
所以,不要像这样调用:
u = users()
u.get_user_by_user_id(1)
u.get_user_by_username('foo')
u.get_users_by_role_and_company('Admin', 'bar')
我会像这样调用通用函数:
u = users()
u.get_user(user_id=1)
u.get_user(username='foo')
u.get_user(role='Admin', company='bar')
到目前为止,这是我能想到的:
def get_user(**kwargs):
where_clause = ''
for key, value in kwargs.items():
where_clause += '{} == {} AND '.format(key, value)
where_clause = where_clause[:-5] # remove final AND
stmt = "SELECT * FROM {tablename} WHERE {where_clause};".format(tablename='users', where_clause=where_clause)
return self.connection.execute(stmt)
有什么方法可以使用 ORM 样式来创建语句吗?
但您已经完成了所有艰苦的工作。这只是组合您创建的函数、初始化输入变量并在其中加入一些 if
语句的问题。
def get_user(self, user_id=0, username='', role='', company=''):
if user_id:
stmt = self.users.select().where(self.users.c.user_id == user_id)
return self.connection.execute(stmt)
elif username:
stmt = self.users.select().where(self.users.c.username == username)
return self.connection.execute(stmt)
elif role and company:
stmt = self.users.select().where(self.users.c.role == role).where(self.users.c.company == company)
return self.connection.execute(stmt)
else:
print('Not adequate information given. Please enter "ID" or "USERNAME", or "ROLE"&"COMPANY"')
return
请注意,user_id
已被初始化为 0
,因此它的布尔值是 False
。如果 0 id 是可能的,请将其直接设置为 False
。因此,由于输入不能是 'random',您是否有理由要使用 **kwargs
?
或者,如果组合的数量太多而无法编码,我会走不同的路线(SQL-injection-valnurable 脚本传入!)如下:
def get_user(self, query):
form_query = 'SELECT user FROM {} WHERE {}'.format(table_name, query)
# now execute it and return whatever it is you want returned
您不再将变量传递给函数,而是将字符串附加到查询并执行。 不用说,你必须非常小心。
试试这样的东西:
def get_user(self, **kwargs):
if 'user_id' in kwargs:
(...)
elif 'username' in kwargs:
(...)
elif all(a in ['role','company'] for a in kwargs):
(...)
else:
(...)
完全通用化,因此只要 table 中存在具有该名称的字段,任何合法字段名称的组合都可以接受。神奇之处在于 getattr
,它允许我们动态查找我们感兴趣的字段(如果使用不存在的字段名称调用则引发 AttributeError
):
def get_user(self, **kwargs):
# Basic query
stmt = self.users.select()
# Query objects can be refined piecemeal, so we just loop and
# add new clauses, assigning back to stmt to build up the query
for field, value in kwargs.items():
stmt = stmt.where(getattr(self.users.c, field) == value)
return self.connection.execute(stmt)