Проверка db-моделей на уникальность. Вставить или проигнорировать с помощью Flask-SQLAlchemy
У меня есть вопрос о том, как добавить новые, но уникальные элементы в базу данных.
app = Flask(__name__, template_folder='templates')
app.config.from_object('config')
db = SQLAlchemy(app)
Классы выглядят вот так многие-ко-многим реализации:
connections = db.Table('connections', db.metadata,
db.Column('book_id', db.Integer, db.ForeignKey('books.id')),
db.Column('author_id', db.Integer, db.ForeignKey('authors.id'))
)
class Author(db.Model):
__tablename__ = 'authors'
__searchable__ = ['a_name']
__table_args__ = {'sqlite_autoincrement': True,}
id = db.Column(db.Integer, primary_key=True)
a_name = db.Column(db.String(80), unique=True)
def __repr__(self):
return unicode(self.a_name)
class Book(db.Model):
__tablename__ = 'books'
__searchable__ = ['b_name']
__table_args__ = {'sqlite_autoincrement': True,}
id = db.Column(db.Integer, primary_key=True)
b_name = db.Column(db.String(80), unique=True)
authors = db.relationship('Author', secondary=lambda: connections,
backref=db.backref('books'))
def __repr__(self):
return unicode(self.b_name)
Я хочу добавить только уникальные элементы БД. Если я напишу этот код:
author = Author(a_name = "Author1")
book = Book(b_name = "Book1")
author.books.append(book)
db.session.add(author)
db.session.add(book)
db.session.commit()
И у нас уже был автор с именем "Author1" в нашей базе данных будет ошибка exeption.
IntegrityError: (IntegrityError) column a_name is not unique u'INSERT INTO authors (a_name) VALUES (?)' (u'u0410u0432u0442u043eu04402',)
Нужно ли мне проверять уникальность этого insershions и как? Или есть другое лучшее решение?
3 ответов:
ORM не поддерживает подход" слияния "(например," вставка или замена " и все такое), и с ними также есть много сложностей. Я использую рецептуникального объекта или его вариант. Когда я делаю большое слияние данных, я часто загружаю весь набор объектов, с которыми нужно иметь дело для какого-то конкретного фрагмента, в словарь заранее, так что есть только один оператор SELECT, чтобы загрузить их, а затем просто проверить в этом словаре, как я продолжаю.
На самом деле я нашел не простое и уродливое решение :), но оно работает. Конечно, когда я буду использовать большую базу данных, я буду использовать этотуникальный объект рецепт, который ввел @zzzeek.
new_author = Author(a_name = request.form['author']) new_book = Book(b_name = request.form['book']) author_in_db = Author.query.filter_by(a_name=unicode(new_author)).first() book_in_db = Book.query.filter_by(b_name=unicode(new_book)).first() # both author and book are new and unique if unicode(new_author) != unicode(author_in_db) and \ unicode(new_book) != unicode(book_in_db): new_author.books.append(new_book) db.session.add(new_author) db.session.add(new_book) db.session.commit() # just book is not unique elif unicode(new_author) != unicode(author_in_db): new_author.books.append(book_in_db) db.session.add(new_author) db.session.commit() # just author is not unique elif unicode(new_book) != unicode(book_in_db): author_in_db.books.append(new_book) db.session.add(new_book) db.session.commit()
class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String, unique=True) fullname = Column(String) password = Column(String) insert_command = User.__table__.insert( prefixes=['OR IGNORE'], values=dict(name='MyName', fullname='Slim Shady', password='******') ) session.execute(insert_command) session.commit()Заменить также работает
prefixes=['OR REPLACE']
Comments