Как я могу предотвратить воссоздание детей в отношениях SQLAlchemy «один ко многим»? - PullRequest
0 голосов
/ 12 июля 2011

Я использую Python 2.6.6 и SQLAlchemy 0.6.6 для обработки отношения один-ко-многим в моей базе данных и не уверен, как предотвратить добавление SQLAlchemy новых дочерних записей в случае, когда подобные данные уже существуют.

Код базы данных:

from sqlalchemy import *
from sqlalchemy.orm import backref, relationship, sessionmaker, create_session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

# Parent table, no foreign key.
class Author(Base):
    __tablename__ = 'authors'

    id = Column(Integer, primary_key=True)
    username = Column(String)
    author_metadata = relationship('AuthorMetadata', backref='author')

# Child table, many records with same author_id.
class AuthorMetadata(Base):
    __tablename__ = 'author_metadata'

    id = Column(Integer, primary_key=True)
    author_id = Column(Integer, ForeignKey('authors.id'))
    metakey = Column(String)
    metavalue = Column(Text)

Пример сценария:

if __name__ == '__main__':
    engine = create_engine('database_details', pool_recycle=90)
    session = create_session(bind=engine)

    author = session.query(Author).filter_by(username='Godfrey').first()
    if not author:
        author = Author()
    author.username = 'Godfrey'
    author.author_metadata = [
        AuthorMetadata(metakey='location', metavalue='New York'),
        AuthorMetadata(metakey='posts', metavalue='5')]
    session.add(author)
    session.flush()

При первом запуске примера сценария в базе данных появляется следующее (как и ожидалось):

dev=# select id from authors where username = 'Godfrey';
  id  
------
 5025
(1 row)

dev=# select id, author_id, metakey, metavalue from author_metadata order by id desc limit 2;
  id   | author_id | metakey  | metavalue 
-------+-----------+----------+-----------
 85090 |      5025 | posts    | 5
 85089 |      5025 | location | New York
(2 rows)

Однако, если я снова запустил пример сценария, вы увидите, что идентификаторы авторов существующей записи метаданных были установлены в ноль, и были вставлены новые записи:

dev=# select id, author_id, metakey, metavalue from author_metadata order by id desc limit 4;
  id   | author_id | metakey  | metavalue 
-------+-----------+----------+-----------
 85092 |      5025 | posts    | 5
 85091 |      5025 | location | New York
 85090 |           | posts    | 5
 85089 |           | location | New York
(4 rows)

Я неЭто удивительно, но мне интересно, есть ли хороший способ сообщить SQLAlchemy, что он должен вставлять / изменять / удалять строки метаданных автора, только если новый список метаданных отличается от существующего списка.

1 Ответ

1 голос
/ 12 июля 2011

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

Ваш вариант использования вполне соответствует attribute_mapped_collection и association_proxy , так что вы, вероятно, захотите использовать одну из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...