Как разделить ORM и функции SQLAlchemy на два разных файла

#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