1

I'm following this tutorial to build a user login system within Flask using Python 2.7.

Intro to Flask: Signing In and Out

I have this Flask application structure.

flaskapp/
└── app/
        ├── user/
        │      ├── __init__.py
        │      ├── static/
        │      ├── templates/
        │      ├── forms.py
        │      ├── routes.py
        └── runserver.py

Within the tutorial, it has me edit this file.

app/intro_to_flask/routes.py

Within that file you have this code.

from user import app
from flask import render_template, request, flash
from forms import ContactForm
from flask.ext.mail import Message, Mail

mail = Mail()
.
.
.
# @app.route() mappings start here

I get this error.

ImportError: cannot import name app

That being said, I cannot do from user import app. I've tried:

from . import app

I don't really know how to explain the question here, but I am editing a python file within the user directory that is trying to import an outer directory within itself? How can you possibly do from user import app if the app directory does not live within the user directory? What am I missing here?

Within the runserver.py, I'm able to do it because I assume runserver.py lives in the app directory. I cannot do it in routes.py though.

If I cannot import app, I cannot define routes within Flask as such:

@app.route('/')
def index():
    return "Testing route!"
Fastidious
  • 1,249
  • 4
  • 25
  • 43
  • @g.d.d.c - I do not believe this is a duplicate. This problem has little to do with relative imports. The variable in question actually needs to be defined in `__init__.py`, I suspect it was left off, or a different name was used from what the tutorial used. The imports are otherwise correct, I think. – ArtOfWarfare Feb 28 '16 at 04:29
  • 1
    Try `import user; print(user)` in your script, before the line that fails. Post what it prints here - might give us some more insight with what's happening. – ArtOfWarfare Feb 28 '16 at 04:41
  • @ArtOfWarfare: – Fastidious Feb 28 '16 at 04:49
  • 1
    Okay... so it's importing the right file then (right? Or is that path to an unrelated but similarly named project?) I'm back to suspecting the problem is your `__init__.py` file. Can you edit your question to include the full contents of `__init__.py`? – ArtOfWarfare Feb 28 '16 at 04:54
  • I figured it out. It's actually the order of importing that was causing the issue. I use PyCharm IDE and it placed the importing at the top of the init.py file when it should be after. I'll supply an answer below if you want to see. – Fastidious Feb 28 '16 at 04:58

3 Answers3

2

In the tutorial you link to, app is defined inside of the __init__.py file, like this:

from flask import Flask

app = Flask(__name__)
# ... The tutorial has a lot more below this, too - it's all probably important.

The variable called app within your module (called intro_to_flask in the tutorial and user in your case) is not related to that folder named app.

Have the correct contents in __init__.py and I think this will work out.

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
  • My __init__.py file does contain the Flask module and defines app = Flask(__name__). It's still failing to import app from within users. – Fastidious Feb 28 '16 at 04:36
  • Thanks ArtOfWarfare. Technically you were right with the init.py file not having right contents. I'll give you the correct answer here because it led me to finding out the problem in the order of imports. I guess it was a minor overlook, but I'm still a noob. – Fastidious Feb 28 '16 at 05:10
0

This is a problem with your understanding of how the Python packaging and import system works (as far as I can tell). The tutorial you've referenced uses a far simpler structure (everything in two files).

I would simplify your structure to a single package (folder) with several files (modules). Here is how the imports work.

from x import y is saying "from [this module or package] import [something]"

A module = a file

A package = a folder (with the __init__.py file in it **REQUIRED)

You cannot have one module importing something from a module it cannot reach. (i.e. a package that it cannot find)

You also cannot have circular imports. Such as this:

from x import y
a = 1

# ... and then inside x.py

from z import a

Won't work.

Hopefully this will help you figure out the specifics of your importing problem.

Peter M. Elias
  • 1,204
  • 10
  • 22
  • Ahh, you're right. I guess it's trying to import app from the init.py file where app = Flask() is defined. How would I import app = Flask() from init.py to the routes.py file? – Fastidious Feb 28 '16 at 04:37
  • `from intro_to_flask import app` – Peter M. Elias Feb 28 '16 at 04:41
  • Then that's the problem. from intro_to_flask import app is failing to import app in routes.py even though the init.py file within intro_to_flask has app defined as app = Flask() – Fastidious Feb 28 '16 at 04:46
0

Answering my own question here.

The problem was the order of the imports. I use a popular IDE called PyCharm that follows the PEP 8 standard. It placed the imports at the top of the file during refactoring, which caused app to fail on importing.

This is the original code of my init.py file that was refactored (PEP 8):

from flask import Flask
from routes import mail
import user.routes

app = Flask(__name__)

app.secret_key = 'development key'

app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 465
app.config["MAIL_USE_SSL"] = True
app.config["MAIL_USERNAME"] = 'removed'
app.config["MAIL_PASSWORD"] = 'removed'

mail.init_app(app)

The correct code that fixed the problem:

from flask import Flask

app = Flask(__name__)

app.secret_key = 'development key'

app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 465
app.config["MAIL_USE_SSL"] = True
app.config["MAIL_USERNAME"] = 'removed'
app.config["MAIL_PASSWORD"] = 'removed'

from routes import mail
mail.init_app(app)

import user.routes
Fastidious
  • 1,249
  • 4
  • 25
  • 43