0

I'm writing a flask site and I'm not sure which files are supposed to contain my run, configure, and setup code. My directory structure looks like this:

/
  dev_settings.py
  run.py
  various other files... (schema, production_settings, etc)
  /sitename
    __init__.py
    various other files... (routes, models, etc)

And the contents of dev_settings.py, run.py, and __init__.py are below. My understanding of it is like this:

  • run.py is the entry point.
  • It gets an app object from sitename/__init__.py and imports config settings from dev_settings (or production_settings).
  • At some point, the (rest of the) setup code in __init__.py is run? This is the code in-between "app = Flask(__name__)" and "import sitename.admin_routes"

I can't however access any custom config variables from __init__.py (for example, by trying "print app.config['stuff imported from dev_settings']") and now I'm running into a problem because I want to upload files and I can't create and configure an UploadSet without the UPLOADED_IMAGES_DEST I set in dev_settings.py

Where am I going wrong here? Why is run.py's app.config not visible anywhere else? Do I absolutely have to condense run.py and __init__.py? I prefer having them separate.

dev_settings.py

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#dev_settings.py

import os
from flask.ext.uploads import IMAGES

basedir = os.path.abspath(os.path.dirname(__file__))

DEBUG = True
TESTING = False
SECRET_KEY = 'SECRET'
DATABASE = 'dev.db'
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, DATABASE)
UPLOADED_IMAGES_DEST = 'site/images/'
UPLOADED_IMAGES_ALLOW = IMAGES
UPLOADED_IMAGES_URL = 'images/'

run.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# run.py

from flask import Flask
import socket
from sitename import app

if __name__ == '__main__':
    if socket.gethostname() == 'dev_laptop':
        app.config.from_object('dev_settings')
    else:
        app.config.from_object('prod_settings')
    app.run()

__init__.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# __init__.py

from flask import Flask
from flask.ext.login import LoginManager
from flask_wtf.csrf import CsrfProtect
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bcrypt import Bcrypt

app = Flask(__name__)

login_manager = LoginManager()
login_manager.init_app(app)
CsrfProtect(app)
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)


import sitename.admin_routes
thekthuser
  • 706
  • 1
  • 12
  • 28
  • When you import `sitename/__init__.py`, it executes fully before `run.py` resumes execution. That means the config is set after you initialize your extensions. – dirn Apr 18 '16 at 00:39
  • If I were to move some of the setup lines, let's say "db = SQLAlchemy(app)" into run.py, how would I access that variable inside the main project? I wouldn't be able to run "from sitename import db" anymore. Is there a different way to import it? – thekthuser Apr 18 '16 at 00:49
  • You may want to look into some of the [common application layouts](http://stackoverflow.com/a/14421367/978961). – dirn Apr 18 '16 at 01:01
  • Hmm, so I think I should move everything except "from sitename import app" and "app.run()" out of run.py I don't have time to try that right now, but it makes sense and I'll report back when I can. Thanks. – thekthuser Apr 18 '16 at 01:12

1 Answers1

0

My original problem stemmed from not fully understanding the 'Larger Applications' page linked from the page dirn linked (http://flask.pocoo.org/docs/0.10/patterns/packages/). The solution is to have run.py import app, call app.run() and nothing else. My updated code is below.

run.py

#!/usr/bin/env python                                                                                
# -*- coding: utf-8 -*-                                                                              
# run.py                                                                                             

from sitename import app                                                                                

app.run()

init.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# __init__.py

from flask import Flask
from flask.ext.login import LoginManager
from flask_wtf.csrf import CsrfProtect
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bcrypt import Bcrypt
import socket

app = Flask(__name__)

#if __name__ == '__main__':
if socket.gethostname() == 'dev_laptop':
    app.config.from_object('dev_settings')
else:
    app.config.from_object('prod_settings')

login_manager = LoginManager()
login_manager.init_app(app)
CsrfProtect(app)
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
configure_uploads(app, images)

import sitename.admin_routes
thekthuser
  • 706
  • 1
  • 12
  • 28