Многие-ко-многим в sqlalchemy. Предотвращение вставки SQLAlchemy в таблицу, если тег уже существует

У меня есть несколько таблиц с сопоставлением ORM, которые (уменьшены) выглядят следующим образом:

class Tag(Base): __tablename__ = 'tags' tag_name = Column(String, primary_key=True) task2tag_assoc = Table('tasktags', Base.metadata, Column('task_id', UUID, ForeignKey('tasks.task_id', ondelete='cascade'), primary_key=True), Column('tag_name', String, ForeignKey('tags.tag_name', ondelete='cascade'), primary_key=True) ) class Task(Base): __tablename__ = 'tasks' task_id = Column(UUID, primary_key=True) _tags = relationship('Tag', secondary=task2tag_assoc, backref='tasks', collection_class=set) tags = association_proxy('_tags', 'tag_name') def __init__(self, task_id, tags): self.task_id = task_id self.tags = set([tags]) 

С помощью этой настройки я могу создать задачу с новыми тегами. Он создает строку тега в таблице tags , а затем создает связь с новой задачей, просто отлично в таблице tasktags .

 t = Task(task_id = uuid4(), tags=['foo', 'bar']) #this works 

Проблема возникает, когда я пытаюсь создать задачу с тегом, который уже существует в таблице tags .

 t2 = Task(task_oid = uuid4(), tags=['foo', 'baz']) #this will give an integrity error 

Кажется, SQLAlchemy всегда пытается вставить тег в таблицу тэгов, независимо от того, существует ли она уже. Мне бы очень хотелось создать ассоциацию только в том случае, если тег уже существует. Похоже, это было бы довольно нормально во многих ситуациях, но я не могу найти нигде в документации, показывающей, что я могу делать неправильно.

Есть ли способ получить поведение, которое я хочу?

Для фона я использую postgresql 9.1 DB с драйвером psycopg2, а SQLAlchemy 0.7.9 (Python 2.7.3)

Вещи, которые я рассматриваю как последнее средство: теги технически являются первичным ключом, и больше ничего, я мог бы избежать просто таблицы тегов task_id-> и таблицы тегов. Но я хотел бы иметь возможность прикреплять метаданные к самим тегам по дороге, если это становится необходимым.

2 Solutions collect form web for “Многие-ко-многим в sqlalchemy. Предотвращение вставки SQLAlchemy в таблицу, если тег уже существует”

для рецепта «только уникальные теги» Я обычно использую уникальный рецепт объекта или его вариант: http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject .

Для этого, естественно, требуется SELECT для определенной строки, чтобы определить, существует ли она в первую очередь. Метод «upsert», используя команды, специфичные для базы данных, для INSERT или UPDATE, на основе определения на стороне базы данных напрямую не поддерживается ORM прямо сейчас. Вы все равно на Postgresql, который фактически не поддерживает какую-либо собственную функцию «upsert», кроме одной очень неудобной системы, использующей общие табличные выражения.

Попробуйте удалить связанные ссылки, такие как t2._tags = []

 t2 = Task(task_oid = uuid4()) t2._tags = [] tags = ['foo', 'baz'] for tag in tags: t2._tags.append(Tag(tag)) 
  • Использование сеанса SQLAlchemy из Flask повышает «объекты SQLite, созданные в потоке, могут использоваться только в том же потоке»
  • Как сделать соединение mysql, требующее CA-CERT с sqlalchemy или SQLObject
  • Как отправить результаты запроса в поле WTForm?
  • Sqlalchemy возвращает «устаревшие» строки?
  • SQLAlchemy запрос, в котором столбец содержит подстроку
  • Как создать ENUM в SQLAlchemy?
  • Передача выражений в функции в python?
  • SQLAlchemy ORM с динамической схемой таблиц
  • Хранение pandas DataFrames в моделях SQLAlchemy
  • Flask-Sqlalchemy + Sqlalchemy-searchable возвращающий пустой список
  • sqlite удалить символы un utf-8
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.