1

I am working on expanding my flask skills and have worked on the treehouse flask social network project and got it to work. I am now playing with changing settings and allowing social login I have moved over to flask-security from plain bcrypt as it is a requirement of flask-social. I have separate app and models files and I am running into RuntimeError: working outside of application context when I try to use the utils.encrypt_password() function it throws the error. I can get it to remove the error by doing from app import app then it states that my database is not an attribute of the module.

I am totally confused I have googled the issue but keep getting errors with peoples suggestions wondering if someone could explain what I am doing wrong. Here is a link to a question i think might be similar but I don't understand in terms of my code. I have posted my code below to show you my user model and the top half of my app.py as these are the two parts that are in the stacktraces.

Models.py

import datetime
#from app import app
from flask.ext.login import UserMixin
from flask.ext.security import Security, RoleMixin, utils
from peewee import *

DATABASE = SqliteDatabase('social.db')
#DATABASE = SqliteDatabase(None)

class User(UserMixin, Model):
    username = CharField(unique=True)
    email = CharField(unique=True)
    password = CharField(max_length=100)
    joined_at = DateTimeField(default=datetime.datetime.now)
    is_admin = BooleanField(default=False)

    class Meta:
        database = DATABASE
        order_by = ('-joined_at',)

    def get_posts(self):
        return Post.select().where(Post.user == self)

    def get_stream(self):
        return Post.select().where(
            (Post.user << self.following()) |
            (Post.user == self))

    def following(self):
        return (
            User.select().join(
                    Relationship, on=Relationship.to_user
            ).where(
                Relationship.from_user == self
            )
        )

    def followers(self):
        return (
            User.select().join(
                Relationship, on=Relationship.from_user
            ).where(
                Relationship.to_user == self
            )
        )

    @classmethod
    def create_user(cls, username, email, password, admin=False):
        try:
            with DATABASE.transaction():
                cls.create(
                    username=username,
                    email=email,
                    password=utils.encrypt_password(password),
                    is_admin=admin)
        except IntegrityError:
            raise ValueError("User already exists")

def initialise():
    #DATABASE.init_app(app)
    DATABASE.connect()
    DATABASE.create_tables([User, Post, Relationship, Role, UserRoles, Connection], safe=True)
    DATABASE.close()

app.py

from flask import (Flask, g, render_template, flash, redirect, url_for, abort, session, request )
from flask.ext.login import LoginManager, login_user, logout_user, login_required, current_user
from flask.ext.social import Social, PeeweeConnectionDatastore
from flask.ext.security import PeeweeUserDatastore, Security
from flask.ext.social.utils import get_provider_or_404
from flask.ext.social.views import connect_handler
from peewee import *

import forms
import models

DEBUG = True
PORT = 8000
HOST = '0.0.0.0'

app = Flask(__name__)
app.secret_key = 'tfdghsf3wquhivfcdsz5.5432jkicdsahuihuj7564jinjnf'

app.config['SECURITY_PASSWORD_HASH'] = 'pbkdf2_sha512'
app.config['SECURITY_PASSWORD_SALT'] = '1b3kxc8s9fdsa9431vbgvhui43212ijkdrdwui'

app.config['SOCIAL_GOOGLE'] = {
    'consumer_key': '1048991051512-6k0vianfkdece33tool0el7pg72h5lku.apps.googleusercontent.com',
    'consumer_secret': 'kDyeeetXqIEq7G9LfGfozLH9'
}
DATABASE = SqliteDatabase('social.db')
app.config['SECURITY_POST_LOGIN'] = '/profile'
user_datastore = PeeweeUserDatastore(models.DATABASE, models.User, models.Role, models.UserRoles)
social_datastore = PeeweeConnectionDatastore(models.DATABASE, models.Connection)
security = Security(app, user_datastore)
social = Social(app, social_datastore)

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

EDIT: After looking further into the issue it seems like it might be an issue with flask-security as I implemented a test function in my main app.py and that two gave the same runtime error.

Community
  • 1
  • 1
bobthemac
  • 1,172
  • 6
  • 26
  • 59

1 Answers1

0

The answer to this question actually lies in the location of my user creation. I had left it where it was in the main section where my program runs code bellow shows this and it looks like it was out of context I moved my default user creation to a function with the @app.before_first_request decorator and it now works.

if __name__ == '__main__':
    try:
            models.User.create_user(
                username='BenBrown',
                email='ben@aperturedigital.uk',
                password='password',
                admin=True
            )
    except ValueError:
        pass

    app.run(debug=DEBUG, host=HOST, port=PORT)
bobthemac
  • 1,172
  • 6
  • 26
  • 59