#python #sqlalchemy #orm
Вопрос:
Я написал некоторый код для приложения, в котором некоторая информация хранится в базе данных SQLite3. Поэтому я использовал SQLAlchemy и настроил объектно-реляционный сопоставитель следующим образом:
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# Setting up SQLAlchemy to connect to the local SQLite3 database
Base = declarative_base()
engine = create_engine('sqlite:///:main:', echo=True)
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind=engine)
session = Session()
Два основных класса, для которых информация хранится в базе данных, выглядят следующим образом:
class Habit(Base):
__tablename__ = 'habit'
habit_id = Column('habit_id', Integer, primary_key=True)
name = Column('name', String, unique=True)
periodicity = Column('periodicity', String)
start_date = Column('start_date', Date)
class HabitEvent(Base):
__tablename__ = 'habit_event'
event_id = Column('event_id', Integer, primary_key=True)
date = Column('date', Date)
habit_id = Column('fk_habit_id', Integer, ForeignKey(Habit.habit_id))
Вот как мой main.py должно выглядеть так. Теперь я написал несколько функций для добавления объектов класса Habit или HabitEvent и их анализа. Вот пример:
def get_habits():
"""Lists all habits, including habit id, periodicity and start date."""
habits = session.query(Habit).all()
for habit in habits:
print(str(habit.habit_id) ', ' str(habit.name) ', '
str(habit.periodicity) ', Start Date: '
str(habit.start_date.strftime('%A, %B %d, %Y')))
Теперь я хочу отделить функции от настройки ORM. Я хотел бы иметь main.py содержащий настройку ORM и классы, а также analytics.py который содержит все функции. Когда я делаю это и импортирую функции из analytis.py к тому main.py и попробуйте их назвать, он явно не знает класса Habit и HabitEvent, так как они не определены в analytics.py.
Вот мой последний вопрос: есть ли возможность разделить ORM и функции анализа на два предложенных файла? Или они должны быть частью одного и того же файла?
Ответ №1:
да, они могут быть разделены на несколько файлов.
один из способов сделать это-передать сеанс и модели функции:
def get_habits(session, Habit):
"""Lists all habits, including habit id, periodicity and start date."""
habits = session.query(Habit).all()
for habit in habits:
print(str(habit.habit_id) ', ' str(habit.name) ', '
str(habit.periodicity) ', Start Date: '
str(habit.start_date.strftime('%A, %B %d, %Y')))
и в main.py
файле вы можете вызвать эту функцию после импорта следующим образом:
get_habits(session, Habit)
session
является session = Session()
и Habit
является моделью(классом), которую вы хотите использовать в функции.
Комментарии:
1. Делая это таким образом, python ожидал бы аргумента для сеанса и выдает ошибку, что значение не было получено.
2. не могли бы вы показать мне сообщение об ошибке и способ, которым вы вызвали функцию?
3. Я изменил функцию так, как вы предложили, и я использую интерфейс командной строки Google Fire для вызова функции через bash. Я попробовал сделать это со следующими строками.
python main.py get_habits
Здесь я получаю сообщение об ошибке:ERROR: The function received no value for the required argument: session
Когда я используюsession
иHabit
в качестве аргументов, я получаю следующую ошибку:habits = session.query(Habit).all() AttributeError: 'str' object has no attribute 'query'
Так как python принимает сеанс в виде строки.
Ответ №2:
Я решил проблему, разделив код на несколько файлов:
- main.py содержит интерфейс командной строки и импортирует все функции из analytics.py
- orm.py содержащий настройку объектно-реляционного сопоставления
- classes.py содержит классы для orm и импортирует базу из orm.py
- аналитика.py, содержащий все функции и импорт классов из classes.py и сессия от orm.py