Python 我可以在SQLAlchemy中使用带参数的上下文敏感函数吗?
这里有一个小表格,以起始地址、结束地址和范围内的IP数的形式保存IP地址范围Python 我可以在SQLAlchemy中使用带参数的上下文敏感函数吗?,python,sqlalchemy,Python,Sqlalchemy,这里有一个小表格,以起始地址、结束地址和范围内的IP数的形式保存IP地址范围 class IpRange(Base): __tablename__ = 'ip_range' ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True) start_ip = Column(String(15)) end_ip = Column(String(15)) num_ips
class IpRange(Base):
__tablename__ = 'ip_range'
ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True)
start_ip = Column(String(15))
end_ip = Column(String(15))
num_ips = Column(Integer)
我想做的是能够使用各种样式创建对象,并让类了解如何填充自己的字段
foo = IpRange(ip='192.168.0.1')
foo = IpRange(ip='192.168.0.0/24')
foo = IpRange(ip='192.168.0.0-192.168.0.255')
编写一个可以解析各种IP地址/范围符号的函数并不难:
def parseIp(desired_format):
... stuff to parse any valid IP address/network format ...
if desired_format == 'start':
return start_ip
if desired_format == 'end':
return end_ip
if desired_format == 'num_ips':
return num_ips
我希望我可以对我的列使用default
方法来获取每个列所需的数据:
class IpRange(Base):
__tablename__ = 'ip_range'
ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True)
start_ip = Column(String(15), default=parseIp('start'))
end_ip = Column(String(15), default=parseIp('end'))
num_ips = Column(Integer, default=parseIp('num_ips')
但是,这不是有效的SQLAlchemy语法。文档中提到了,但语法不允许将参数传递给函数。因此,即使我可以使用default=parseIp
调用函数,我也无法告诉它我在寻找什么样的返回值
在SQLAlchemy的列规范中是否有这样做的方法
或者作为另一种想法,我应该将parseIp转换为一个助手脚本,只生成新的IpRange对象本身并将其返回给调用者吗?比如:
def parseIp(ipstring):
... parse data ...
return IpRange(start_ip=parsed_start_ip, end_ip=parsed_end_ip, num_ips=parsed_num_ips)
>>> ipobj = parseIp('192.168.0.0/24')
只需重写构造函数。例如:
class IpRange(Base):
def __init__(self, ip=None, **kwargs):
if ip is not None:
self.start_ip, self.end_ip = my_super_awesome_cidr_parser(ip)
else:
super(IpRange, self).__init__(**kwargs)
只需重写构造函数。例如:
class IpRange(Base):
def __init__(self, ip=None, **kwargs):
if ip is not None:
self.start_ip, self.end_ip = my_super_awesome_cidr_parser(ip)
else:
super(IpRange, self).__init__(**kwargs)
好极了我不完全理解它是如何工作的(最后一行特别神秘),但它确实工作。谢谢大家!@GeorgeAdams最后一行调用超类的(
Base
)构造函数,允许您使用默认行为,即通过关键字参数设置属性(例如IpRange(start_ip=“…”,end_ip=“…”)
)。super()
的文档是。我想我明白了。正确的做法(如果没有指定“ip”)是以传统方式创建IpRange
对象(foo=IpRange(start_ip=“…”)
)。我想我们需要为IpRange
使用原始的\uuuu init\uuuu
,但我相信你告诉我的是,IpRange从来没有\uuu init\uuuuu
,只有一个用于Base
。还有一个问题-为什么要调用super(IpRange,self)
而不仅仅是super(IpRange)
?@GeorgeAdams简短的回答:这就是你应该如何调用超类。答案很长:它与多重继承有关。处理多重继承时,解析方法的顺序称为方法解析顺序(mro),不能直接从类本身推断。例如,class Foo(IpRange,Bar):pass
的顺序为Foo
,IpRange
,Bar
,Base
。正如您所看到的,您调用哪个\uuuuu init\uuuu
方法取决于您拥有的对象,而不仅仅是类本身。太棒了!我不完全理解它是如何工作的(最后一行特别神秘),但它确实工作。谢谢大家!@GeorgeAdams最后一行调用超类的(Base
)构造函数,允许您使用默认行为,即通过关键字参数设置属性(例如IpRange(start_ip=“…”,end_ip=“…”)
)。super()
的文档是。我想我明白了。正确的做法(如果没有指定“ip”)是以传统方式创建IpRange
对象(foo=IpRange(start_ip=“…”)
)。我想我们需要为IpRange
使用原始的\uuuu init\uuuu
,但我相信你告诉我的是,IpRange从来没有\uuu init\uuuuu
,只有一个用于Base
。还有一个问题-为什么要调用super(IpRange,self)
而不仅仅是super(IpRange)
?@GeorgeAdams简短的回答:这就是你应该如何调用超类。答案很长:它与多重继承有关。处理多重继承时,解析方法的顺序称为方法解析顺序(mro),不能直接从类本身推断。例如,class Foo(IpRange,Bar):pass
的顺序为Foo
,IpRange
,Bar
,Base
。如您所见,您调用的\uuuu init\uuu
方法取决于您拥有的对象,而不仅仅是类本身。