【发布时间】:2010-08-17 20:07:08
【问题描述】:
我的问题与 sqlalchemy 并没有太大关系,而是与纯 python 相关。
我想控制 sqlalchemy 模型实例的实例化。这是我的代码中的一个 sn-p:
class Tag(db.Model):
__tablename__ = 'tags'
query_class = TagQuery
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), unique=True, nullable=False)
def __init__(self, name):
self.name = name
我想实现,每当实例化一个条目 (Tag('django')) 时,只有在数据库中没有另一个名称为 django 的标签时才应该创建一个新实例。否则,应由 (Tag('django')) 返回对数据库中已存在行的引用,而不是初始化新对象。
到目前为止,我正在确保 Post 模型中标签的唯一性:
class Post(db.Model):
# ...
# code code code
# ...
def _set_tags(self, taglist):
"""Associate tags with this entry. The taglist is expected to be already
normalized without duplicates."""
# Remove all previous tags
self._tags = []
for tag_name in taglist:
exists = Tag.query.filter(Tag.name==tag_name).first()
# Only add tags to the database that don't exist yet
# TODO: Put this in the init method of Tag (if possible)
if not exists:
self._tags.append(Tag(tag_name))
else:
self._tags.append(exists)
它完成了它的工作,但我仍然想知道如何确保 Tag 类本身内部标签的唯一性,以便我可以像这样编写 _set_tags 方法:
def _set_tags(self, taglist):
# Remove all previous tags
self._tags = []
for tag_name in taglist:
self._tags.append(Tag(tag_name))
在编写此问题和测试时,我了解到我需要使用 __new__ 方法。这是我想出的(它甚至通过了单元测试,而且我没有忘记更改_set_tags 方法):
class Tag(db.Model):
__tablename__ = 'tags'
query_class = TagQuery
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), unique=True, nullable=False)
def __new__(cls, *args, **kwargs):
"""Only add tags to the database that don't exist yet. If tag already
exists return a reference to the tag otherwise a new instance"""
exists = Tag.query.filter(Tag.name==args[0]).first() if args else None
if exists:
return exists
else:
return super(Tag, cls).__new__(cls, *args, **kwargs)
困扰我的是两件事:
首先:我收到警告:
DeprecationWarning: object.__new__() takes no parameters
第二:当我这样写时,我得到了错误(我也尝试将参数 name 重命名为 n 但它没有改变任何东西):
def __new__(cls, name):
"""Only add tags to the database that don't exist yet. If tag already
exists return a reference to the tag otherwise a new instance"""
exists = Tag.query.filter(Tag.name==name).first()
if exists:
return exists
else:
return super(Tag, cls).__new__(cls, name)
错误(或类似的):
TypeError: __new__() takes exactly 2 arguments (1 given)
希望你能帮帮我!
【问题讨论】:
标签: python sqlalchemy metaprogramming