Как построить приложение колбы вокруг уже существующей базы данных?
у меня уже есть существующая база данных, которая имеет много столиков и много данных в MySQL
. Я намерен создать Flask
приложение и использовать sqlalchemy вместе с ним. Теперь я спросил на irc и посмотрел вокруг на google и попробовал следующие идеи:
первый Я sqlacodegen для создания моделей из моей DB
. Но потом я немного растерялся и посмотрел еще немного. И я нашел этой.
этот выглядело как элегантное решение.
так второй, я переписал models.py
по решению здесь и сейчас я еще больше запутался. Я ищу лучший подход для создания этого приложения колбы вместе с уже существующей БД.
Я заглянул в документацию колбы, но на самом деле не получил никакой помощи для проекта с уже существующей БД. Есть много хорошего материала для создания чего-то с нуля, создания БД и все такое. Но я действительно смущенный.
обратите внимание, что это мой первый день с Flask
, но у меня есть опыт с Django
, так что основные понятия не являются препятствием. Мне нужно некоторое руководство в выборе наилучшего подхода для этого usecase. Подробное объяснение было бы весьма полезно. По подробному я определенно не ожидаю, что кто-то напишет весь код и ложкой накормит меня на этом, но достаточно, чтобы я начал, то есть легко интегрировал эту БД в flask
через sqlalchemy
. Обратите внимание, что моя БД находится в MySQL
.
8 ответов:
Я бы сказал, что ваш вопрос не имеет никакого отношения к колбе вообще. Например, у вас нет проблем с шаблонами, маршрутами, представлениями или декораторами входа в систему.
где вы боретесь на это в SQLAlchemy.
поэтому мое предложение-игнорировать колбу на некоторое время и сначала привыкнуть к SQLAlchemy. Вам нужно привыкнуть к существующей базе данных и как получить к ней доступ из SQLAlchemy. Используйте некоторые инструменты документации MySQL, чтобы найти свой путь вокруг этого. Начнем с чего-то вроде это (обратите внимание, что это не имеет ничего общего с колбой спросить всех ... пока):
#!/usr/bin/python # -*- mode: python -*- from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base engine = create_engine('sqlite:///webmgmt.db', convert_unicode=True, echo=False) Base = declarative_base() Base.metadata.reflect(engine) from sqlalchemy.orm import relationship, backref class Users(Base): __table__ = Base.metadata.tables['users'] if __name__ == '__main__': from sqlalchemy.orm import scoped_session, sessionmaker, Query db_session = scoped_session(sessionmaker(bind=engine)) for item in db_session.query(Users.id, Users.name): print item
в строке "
engine =
" вам нужно указать свой путь к базе данных MySQL, чтобы SQLAlchemy нашел его. В моем случае я использовал уже существующую базу данных sqlite3.в строке "
class Users(Base)
" вам нужно использовать одну из существующих таблиц в вашей базе данных MySQL. Я знал, что в моей базе данных sqlite3 есть таблица с именем "пользователи".после этого момента SQLalchemy знает, как подключиться к вашему MySQL база данных и она знает об одной из таблиц. Теперь нужно добавить все остальные таблицы, которые вы заботитесь. Наконец, необходимо указать отношения к SQLalchemy. Здесь я имею в виду такие вещи, как один-к-одному, один-ко-многим, многие-ко-многим, родитель-ребенок и так далее. Веб-сайт SQLAlchemy содержит довольно длинный раздел об этом.
после строки "
if __name__ == '__main__'
" просто приходит какой-то тестовый код. Он будет выполнен, если я не импортирую свой скрипт python, а запускаю. Здесь вы видите, что я создаю сеанс БД и это для очень простого запроса.Я предлагаю вам сначала прочитать о важных частях документации SQLAlchemy, например, описательное определение таблицы, модель отношений и способ запроса. Как только вы это узнаете, вы можете изменить последнюю часть моего примера в контроллер (например, используя Python
yield
способ) и написать представление, которое использует этот контроллер.
ключ к подключению ответа Хольгера к контексту колбы - это
db.Model
этоdeclarative_base
объектBase
. Мне потребовалось время, чтобы заметить эту важную фразу в колбу-с SQLAlchemy это документацияниже приведены шаги, которые я использовал для моего приложения:
начать
db
объект в обычной колбе - алхимический способ:db = SQLAlchemy(app)
. Обратите внимание, что вам нужно будет установитьapp.config['SQLALCHEMY_DATABASE_URI'] = 'connection_string'
до этого.связать декларативные база к движку:
db.Model.metadata.reflect(db.engine)
затем вы можете легко использовать существующие таблицы (например. У меня есть таблица под названием здания):
class Buildings(db.Model): __table__ = db.Model.metadata.tables['BUILDING'] def __repr__(self): return self.DISTRICT
теперь ваш
Buildings
класс будет следовать существующей схеме. Вы можете попробоватьdir(Buildings)
в оболочке Python и увидеть все столбцы уже перечислены.
недавно я прошел через то же самое, с дополнительной проблемой связывания моделей между двумя базами данных.
Я Колба-SQLAlchemy и все, что мне нужно было сделать, это определить мои модели так же, как выглядели мои таблицы базы данных, и я смеялся. Мне было трудно понять, как именно должна выглядеть моя структура проекта.
мой проект был Restful API, и это то, что я закончил с:
conf/ __init__.py local.py dev.py stage.py live.py deploy/ #nginx, uwsgi config, etc middleware/ authentication.py app_name/ blueprints/ __init__.py model_name.py #routes for model_name ... models/ __init.py model_name.py __init__.py database.py tests/ unit/ test_etc.py ... run.py
файлы Примечание:
conf/xxx.py
вот как мы говорим Flask-SQLAlchemy, к чему подключаться, плюс вы можете поместить сюда любые другие элементы конфигурации (например, местоположение журнала, отладочный конфиг и т. д.).
SQLALCHEMY_DATABASE_URI = 'mysql://username:password@host:port/db_name'
app_name/___init___.py
здесь я создаю свое приложение и инициализирую БД. Этот объект БД будет импортирован и использован во всем приложении (т. е. в моделях, тестах и т. д.). Я также устанавливаю свой регистратор, инициализирую свои API и схемы элементов и подключаю свое промежуточное программное обеспечение здесь (не показано).
from app_name.database import db from flask import Flask def create_app(*args, **kwargs): env = kwargs['env'] app = Flask(__name__) app.config.from_object('conf.%s' % env) db.init_app(app) return app
app_name/database.py
from flask.ext.sqlalchemy import SQLAlchemy db = SQLAlchemy()
app_name/models/model_name.py
from services.database import db class Bar(db.Model): __tablename__ = 'your_MySQL_table_name' id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True) name = db.Column('WhateverName', db.String(100)) foo = db.Column(db.ForeignKey('another_MySQLTableName.id')) class Foo(db.Model): __tablename__ = 'another_MySQLTableName' id = db.Column('FooId', db.Integer, primary_key=True) ...
run.py
#! /usr/bin/env python from app_name import create_app app = create_app(env='local') if __name__ == '__main__': app.run()
я использую
run.py
для запуска приложения локально, но я использую nginx + uWSGI для запуска приложения в среде dev/stage/live.Я предполагаю, что вы будете иметь в дополнение к этому, хотя.
Я думаю, что самый простой способ использовать существующую базу данных с sqlalchemy-это использовать AutomapBase класса . Пример кода из docs выглядит следующим образом:
from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import Session from sqlalchemy import create_engine Base = automap_base() # engine, suppose it has two tables 'user' and 'address' set up engine = create_engine("sqlite:///mydatabase.db") # reflect the tables Base.prepare(engine, reflect=True) # mapped classes are now created with names by default # matching that of the table name. User = Base.classes.user Address = Base.classes.address session = Session(engine) # rudimentary relationships are produced session.add(Address(email_address="foo@bar.com", user=User(name="foo"))) session.commit() # collection-based relationships are by default named # "<classname>_collection" print (u1.address_collection)
см. SqlAlchemy-Automap для деталей и более сложных применений
Я пытаюсь использовать autogenerated, но ничего не работает или я не мог запустить его. Когда я ищу генерировать код с помощью sqlacodegen я нахожу https://github.com/ksindi/flask-sqlacodegen, Вы можете создать код просто
flask-sqlacodegen mysql://username:password@host:port/db_name --schema yourschema --tables table1,table2 --flask
Я пробовал, и он отлично работает
Это альтернативный способ настроить путь двигателя, описанный в ответе Хольгера. Удобно, если в вашем имени пользователя или пароле есть специальные символы.
from sqlalchemy.engine.url import URL from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base engine_URL = URL('mssql+pymssql', username='DOMAIN\USERNAME', password="""p@ssword'!""", host='host.com', database='database_name') engine = create_engine(engine_URL) Base = declarative_base() Base.metadata.reflect(engine)
Это решение работало для меня
"""Example for reflecting database tables to ORM objects This script creates classes for each table reflected from the database. Note: The class names are imported to the global namespace using the same name as the tables. This is useful for quick utility scripts. A better solution for production code would be to return a dict of reflected ORM objects. """ from sqlalchemy import create_engine, MetaData from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base def reflect_all_tables_to_declarative(uri): """Reflects all tables to declaratives Given a valid engine URI and declarative_base base class reflects all tables and imports them to the global namespace. Returns a session object bound to the engine created. """ # create an unbound base our objects will inherit from Base = declarative_base() engine = create_engine(uri) metadata = MetaData(bind=engine) Base.metadata = metadata g = globals() metadata.reflect() for tablename, tableobj in metadata.tables.items(): g[tablename] = type(str(tablename), (Base,), {'__table__' : tableobj }) print("Reflecting {0}".format(tablename)) Session = sessionmaker(bind=engine) return Session() # set to database credentials/host CONNECTION_URI = "postgres://..." session = reflect_all_tables_to_declarative(CONNECTION_URI) # do something with the session and the orm objects results = session.query(some_table_name).all()
перегонный куб (инструмент за колбой-sqlalchemy) может быть настроен для игнорирования таблиц. Конфигурация не слишком сложна для настройки. смотрите: https://gist.github.com/utek/6163250