Files
runnerspace/app.py

156 lines
4.8 KiB
Python

import os
import random
from datetime import datetime
import click
import pytz
from faker import Faker
from flask import Flask, render_template, request
from flask_wtf.csrf import CSRFProtect, CSRFError
from flask_login import LoginManager, current_user
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash
from database import db
import spacy
csrf = CSRFProtect()
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
if app.config['ENV'] == 'development':
app.config['SECRET_KEY'] = 'secret key goes here'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
# Heroku deployment
if app.config['ENV'] == 'production':
# Deal with spacy model downloading
spacy_model = 'en_core_web_sm'
try:
spacy.load(spacy_model)
except: # If not present, we download
spacy.cli.download(spacy_model)
spacy.load(spacy_model)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', '').replace('postgres://', 'postgresql://', 1)
db.init_app(app)
csrf.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from models import User, Post, Comment
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
from auth import blueprint as auth_blueprint
app.register_blueprint(auth_blueprint)
from routes import blueprint as routes_blueprint
app.register_blueprint(routes_blueprint)
from route_forms import blueprint as forms_blueprint
app.register_blueprint(forms_blueprint)
from static_routes import blueprint as static_blueprint
app.register_blueprint(static_blueprint)
@app.errorhandler(404)
def page_not_found(e):
# note that we set the 404 status explicitly
return render_template('errors/404.html'), 404
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
return render_template('errors/csrf.html', reason=e.description), 400
@app.before_request
def update_last_seen():
if current_user.is_authenticated:
current_user.last_seen = datetime.now(tz=pytz.UTC) # datetime.utcnow doesn't actually attach a timezone
current_user.last_ip = str(request.remote_addr)
db.session.add(current_user)
db.session.commit()
@app.template_filter('pluralize')
def pluralize(number, singular='', plural='s'):
if number == 1:
return singular
else:
return plural
@app.context_processor
def inject():
return dict(now=datetime.utcnow)
# CLI commands setup
@app.shell_context_processor
def shell_context():
"""Provides specific Flask components to the shell."""
return {'app': app, 'db': db}
@app.cli.command("fake")
@click.argument("count")
def create_fake_users(count: int):
fake = Faker()
count = int(count)
users = {}
for _ in range(count):
profile: dict = fake.simple_profile()
users[profile['username']] = profile
for profile in users.values():
new_user = User(username=profile['username'],
name=profile['name'],
password=generate_password_hash('password', method='sha256'),
about_me=fake.paragraph(nb_sentences=5))
db.session.add(new_user)
print(f'Committing {len(users)} users into DB.')
db.session.commit()
all_users: List[User] = User.query.all()
post_count: int = 0
for author in random.choices(all_users, k=count // 2):
new_post = Post(author=author, text=fake.paragraph(nb_sentences=2))
db.session.add(new_post)
post_count += 1
print(f'Committing {post_count} posts into the DB.')
db.session.commit()
comment_count: int = 0
for post in Post.query.all():
for _ in range(random.randint(3, len(all_users) // 4)):
new_comment = Comment(text=fake.paragraph(nb_sentences=1), author=random.choice(all_users), post=post)
db.session.add(new_comment)
comment_count += 1
print(f'Committing {comment_count} comments into the DB.')
db.session.commit()
@app.cli.command("create_all")
def db_create_all() -> None:
with app.app_context():
db.create_all(app=app)
with app.app_context():
db.create_all(app=app)
return app
# Only used for Heroku; use 'flask run' or internal IDE configurations otherwise
app = create_app()
if __name__ == '__main__':
app.run()