Мой вопрос на самом деле не имеет ничего общего с sqlalchemy, а скорее с чистым python.
Я хотел бы проконтролировать создание экземпляров модели sqlalchemy.Это фрагмент из моего кода:
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)
Надеюсь, вы мне поможете!