проблема с переносом колб при рефакторинге кода - PullRequest
0 голосов
/ 18 сентября 2018

Я получил следующую файловую структуру для приложения Python-Flask с flask-migrate:

File Structure

Мои проблемы

1 - я не могу использовать db и create_app внутри manage.py

Когда я делаю:

$ python manage.py db init

Я получил ошибку ниже:

File "/app/main/model/model.py", line 25, in <module>
    class User(db.Model):
NameError: name 'db' is not defined

(дБ определено в main. init .py)

Я пробовал разные варианты, но безуспешно.

Я хочу сохранить manage.py, model.py и main. init .py в отдельных файлах.

2- В модели .py мне понадобятся БД. Как я могу сделать БД доступными для model.py?

Здесь внизу manage.py

# This file take care of the migrations
# in model.py we have our tables
import os
import unittest

from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager

from app.main import create_app
from app.main import db
# # We import the tables into the migrate tool
from app.main.model import model


app = create_app(os.getenv('BOILERPLATE_ENV') or 'dev')

app.app_context().push()

manager = Manager(app)

migrate = Migrate(app, db)

manager.add_command('db', MigrateCommand)

#### If I add  model.py here all should be easier , but still I have the 
#### issue with 
#### from app.main import create_app , db


@manager.command
def run():
    app.run()


@manager.command
def test():
    """Runs the unit tests."""
    tests = unittest.TestLoader().discover('app/test', pattern='test*.py')
    result = unittest.TextTestRunner(verbosity=2).run(tests)
    if result.wasSuccessful():
        return 0
    return 1

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

Это приложение. init .py, где определены db и create_app

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_cors import CORS

from .config import config_by_name

from flask_restful import Resource, Api
# from flask_restplus import Resource
from app.main.controller.api_controller import gconnect, \
     showLogin, createNewTest, getTest, getTests, getIssue, createNewIssue

db = SQLAlchemy()
flask_bcrypt = Bcrypt()


def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config_by_name[config_name])
    cors = CORS(app,
                supports_credentials=True,
                resources={r"/api/*":
                           {"origins":
                            ["http://localhost:3000",
                             "http://127.0.0.1:3000"]}})
    api = Api(app)
    db.init_app(app)
    flask_bcrypt.init_app(app)

    api.add_resource(gconnect, '/api/gconnect')
    api.add_resource(showLogin, '/login')
    api.add_resource(createNewTest, '/api/test')
    api.add_resource(getTest, '/api/test/<int:test_id>')
    api.add_resource(getTests, '/api/tests')
    api.add_resource(getIssue, '/api/issue/<int:issue_id>')
    api.add_resource(createNewIssue, '/api/issue')

    return app

А это (просто одна из таблиц для простоты) моей модели

from sqlalchemy import Column, ForeignKey, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
from sqlalchemy import create_engine
from sqlalchemy.sql import func


# # # This will let sql alchemy know that these clasess
# # # are special Alchemy classes
# Base = declarative_base()



class User(db.Model):

    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250), nullable=False)
    email = db.Column(db.String(250), nullable=False)
    pictures = db.Column(db.String(250))
    role = db.Column(db.String(25), nullable=True)

Мои проблемы:

1 - я не могу использовать db и create_app внутри manage.py

Когда я делаю:

$ python manage.py db init

Я получил ошибку ниже:

Файл "/app/main/model/model.py", строка 25, в Класс User (db.Model): NameError: имя 'db' не определено

(дБ определяется в основном. init .py)

Я пробовал разные варианты, но безуспешно.

Я хочу сохранить manage.py, model.py и main. init .py в отдельных файлах.

2- В модели .py мне понадобятся дБ. Как сделать базу данных доступной для model.py?

1 Ответ

0 голосов
/ 18 сентября 2018

Простым решением является создание отдельного файла инициализации помимо вашего __init__.py.Например, init.py, где вы инициализируете sqlalchemy вместе с другими расширениями.Таким образом, они могут быть импортированы во все модули без проблем с циклическими зависимостями.

Более элегантное решение - использовать прокси Flask current_app и g.Они были созданы, чтобы помочь пользователям Flask обойти любые проблемы с циклическими зависимостями.

Обычно вы инициализируете флягу app в модуле __init__.py, и модулю __init__.py иногда приходится импортировать некоторые переменные из его подпрограммы.модули.Это становится проблематичным, когда подмодули пытаются импортировать инициализированные расширения

Как правило, внешние модули должны импортировать из своих подмодулей, а не наоборот.

Итак, вот один способ, которым вы можете решить свою проблему (цитируется с здесь ):

** __init__.py

from flask import g

def get_db():
    if 'db' not in g:
        g.db = connect_to_database()

    return g.db

@app.teardown_appcontext
def teardown_db():
    db = g.pop('db', None)

    if db is not None:
        db.close()


def init_db():
    db = get_db()

Теперь вы можетелегко импортировать ваше соединение БД в любой другой модуль с помощью:

from flask import g

db = g.db
db.do_something()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...