Чистый импорт Python для моделей — SQL Alchemy

У меня есть фляжное приложение со следующей структурой каталогов:

  • myapp/
    • application.py
    • __init__.py
    • models/
      • __init__.py
      • user.py

Модели используют Flask-SQLAlchemy, поэтому им необходимо иметь доступ к объекту db (экземпляру SQLAlchemy) из application.py.

пользователь.py:

import sys,os
sys.path.append('/path/to/application/package')

from testapp import db

class User(db.Model):
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(255),unique=True)
    age = db.Column(db.Integer)

    def __init__(self,username,age):
        self.username = username
        self.age = age

    def __repr__(self):
        return '<User %r>' % self.username 

Поскольку любой из моделей требуется доступ к экземпляру SQLAlchemy приложения, свойству db, мне приходится кидать весь этот пакет по пути, а затем импортировать из основного модуля приложения. Ради здравомыслия я хотел бы хранить модели в отдельных файлах. Нужно ли будет помещать код пути поверх каждой модели? Есть ли способ лучше? Я бы предпочел не вводить полный путь таким образом, поскольку они могут быть развернуты на разных хостах с разными структурами каталогов. В идеале должен быть какой-то способ внутренней обработки пути, поэтому, когда он используется в качестве другого пользователя через mod_wsgi, мне не нужно вручную изменять код.


person DeaconDesperado    schedule 19.07.2012    source источник


Ответы (1)


1-й подход:

Я закончил со следующей структурой:

  • project_root — also holds some configs, .gitignore file, etc
    • start.py
    • flask_root
      • __init__.py
      • приложение.py
      • module_1
        • __init__.py
        • модели.py
      • module_2
        • __init__.py
        • модели.py

Самый верхний start.py просто запускает приложение:

#! /usr/bin/env python
from flask_root import applicaiton

if __name__ == '__main__':
    application.manager.run()

Python ищет пакеты в каталоге, из которого вы запускаете скрипт , так что теперь их не нужно добавлять в sys.path (как по мне, модификация sys.path выглядит некрасиво). Теперь у вас есть полноценный пакет python flask_root, и вы можете импортировать из него все, из любого места вашего приложения:

from flask_root.application import db

2-й подход:

Если вы запустите приложение Flask из его каталога,

./application.py runserver

каталог, из которого вы начали, недоступен как пакет python, даже если в нем есть __init__.py.

Однако с макетом вашего каталога вы можете сделать следующий трюк:

модели/__init__.py:

from application import db
...

models/user.py:

from . import db
...

Первый подход более чистый и универсальный. Второй вариант может быть полезен, когда вам нужно использовать одни и те же чертежи для нескольких проектов Flask.

person Alex Lokk    schedule 19.07.2012
comment
Мне нравится! Один вопрос... если у меня есть тестовая логика в каждом из файлов модели в условном выражении __main__, они, вероятно, не будут работать с этим подходом. Я должен положить юнит-тесты в корень с запуском, верно? - person DeaconDesperado; 20.07.2012
comment
Вы можете использовать расширение Flask-Script, и ваши тесты будут доступны через ./application.py ‹test_command›. Оставьте тестовый код в его модуле (для небольших тестов это приятнее и проще), но запустите его с помощью декоратора Flask-Script, он создаст команду. ... также можно создать декоратор, который будет добавлять тестовые функции в некий глобальный список, чтобы запускать их все сразу (по команде, или просто при запуске в режиме отладки). - person Alex Lokk; 20.07.2012