python import from parent directories '__init_

2019-08-16 08:45发布

问题:

I am working on a flask app with the following structure:

.
├── app
│   ├── __init__.py
│   ├── forms
│   │   └── login.py
│   ├── models
│   │   ├── __init__.py
│   │   └── user.py
│   ├── templates
│   │   ├── base.html
│   │   ├── home.html
│   │   └── login.html
│   └── views
│       ├── __init__.py
│       └── login.py

in app/__init__.py I am creating an instance of the LoginManager extension:

from flask import Flask
from config import app_config
from flask_login import LoginManager

def create_app(config_mode='development'):
    """Wrapping app creation in factory according to specified config."""

    app = Flask(__name__, template_folder='templates')

    ...

    # register login manager extension
    login = LoginManager(app)

    return app

I now need to import login in app/models/user.py in order to provide the user_loader implementation:

from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin


from . import db
from .. import login

class User(UserMixin, db.Model):
    """User model."""

    ...

@login.user_loader
def load_user(id):
    return User.query.get(int(id))

However, any attempt to do this fails with:

from .. import login
ImportError: cannot import name 'login'

My question is: is there any way to import from a parent directories __init__.py file, or am I making some other mistake here?

I tried a number of different combinations of absolute and relative imports but all yield the same result, and searched extensively on SO and google, but did not find a direct answer to my question. I would like to keep the user.py module the current directory as the directory structure is nice and concisely organized.

Thanks in advance

edit: clarified import location

回答1:

You should create the instance of LoginManager out of create_app function. And then you can configure it for login with init_app method.

from flask import Flask
from flask-login import LoginManager

login_manager = LoginManager()

def create_app(config):
    app = Flask(__name__)
    login_manager.init_app(app)
    return app