forked from miguelgrinberg/microblog
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Chapter 15: A Better Application Structure (v0.15)
- Loading branch information
1 parent
bf464e1
commit 5f8cd88
Showing
32 changed files
with
563 additions
and
473 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from flask import Blueprint | ||
|
||
bp = Blueprint('auth', __name__) | ||
|
||
from app.auth import routes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from flask import render_template, current_app | ||
from flask_babel import _ | ||
from app.email import send_email | ||
|
||
|
||
def send_password_reset_email(user): | ||
token = user.get_reset_password_token() | ||
send_email(_('[Microblog] Reset Your Password'), | ||
sender=current_app.config['ADMINS'][0], | ||
recipients=[user.email], | ||
text_body=render_template('email/reset_password.txt', | ||
user=user, token=token), | ||
html_body=render_template('email/reset_password.html', | ||
user=user, token=token)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
from flask import render_template, redirect, url_for, flash, request | ||
from werkzeug.urls import url_parse | ||
from flask_login import login_user, logout_user, current_user | ||
from flask_babel import _ | ||
from app import db | ||
from app.auth import bp | ||
from app.auth.forms import LoginForm, RegistrationForm, \ | ||
ResetPasswordRequestForm, ResetPasswordForm | ||
from app.models import User | ||
from app.auth.email import send_password_reset_email | ||
|
||
|
||
@bp.route('/login', methods=['GET', 'POST']) | ||
def login(): | ||
if current_user.is_authenticated: | ||
return redirect(url_for('main.index')) | ||
form = LoginForm() | ||
if form.validate_on_submit(): | ||
user = User.query.filter_by(username=form.username.data).first() | ||
if user is None or not user.check_password(form.password.data): | ||
flash(_('Invalid username or password')) | ||
return redirect(url_for('auth.login')) | ||
login_user(user, remember=form.remember_me.data) | ||
next_page = request.args.get('next') | ||
if not next_page or url_parse(next_page).netloc != '': | ||
next_page = url_for('main.index') | ||
return redirect(next_page) | ||
return render_template('auth/login.html', title=_('Sign In'), form=form) | ||
|
||
|
||
@bp.route('/logout') | ||
def logout(): | ||
logout_user() | ||
return redirect(url_for('main.index')) | ||
|
||
|
||
@bp.route('/register', methods=['GET', 'POST']) | ||
def register(): | ||
if current_user.is_authenticated: | ||
return redirect(url_for('main.index')) | ||
form = RegistrationForm() | ||
if form.validate_on_submit(): | ||
user = User(username=form.username.data, email=form.email.data) | ||
user.set_password(form.password.data) | ||
db.session.add(user) | ||
db.session.commit() | ||
flash(_('Congratulations, you are now a registered user!')) | ||
return redirect(url_for('auth.login')) | ||
return render_template('auth/register.html', title=_('Register'), | ||
form=form) | ||
|
||
|
||
@bp.route('/reset_password_request', methods=['GET', 'POST']) | ||
def reset_password_request(): | ||
if current_user.is_authenticated: | ||
return redirect(url_for('main.index')) | ||
form = ResetPasswordRequestForm() | ||
if form.validate_on_submit(): | ||
user = User.query.filter_by(email=form.email.data).first() | ||
if user: | ||
send_password_reset_email(user) | ||
flash( | ||
_('Check your email for the instructions to reset your password')) | ||
return redirect(url_for('auth.login')) | ||
return render_template('auth/reset_password_request.html', | ||
title=_('Reset Password'), form=form) | ||
|
||
|
||
@bp.route('/reset_password/<token>', methods=['GET', 'POST']) | ||
def reset_password(token): | ||
if current_user.is_authenticated: | ||
return redirect(url_for('main.index')) | ||
user = User.verify_reset_password_token(token) | ||
if not user: | ||
return redirect(url_for('main.index')) | ||
form = ResetPasswordForm() | ||
if form.validate_on_submit(): | ||
user.set_password(form.password.data) | ||
db.session.commit() | ||
flash(_('Your password has been reset.')) | ||
return redirect(url_for('auth.login')) | ||
return render_template('auth/reset_password.html', form=form) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,35 @@ | ||
import os | ||
import click | ||
from app import app | ||
|
||
|
||
@app.cli.group() | ||
def translate(): | ||
"""Translation and localization commands.""" | ||
pass | ||
|
||
|
||
@translate.command() | ||
@click.argument('lang') | ||
def init(lang): | ||
"""Initialize a new language.""" | ||
if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): | ||
raise RuntimeError('extract command failed') | ||
if os.system( | ||
'pybabel init -i messages.pot -d app/translations -l ' + lang): | ||
raise RuntimeError('init command failed') | ||
os.remove('messages.pot') | ||
|
||
|
||
@translate.command() | ||
def update(): | ||
"""Update all languages.""" | ||
if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): | ||
raise RuntimeError('extract command failed') | ||
if os.system('pybabel update -i messages.pot -d app/translations'): | ||
raise RuntimeError('update command failed') | ||
os.remove('messages.pot') | ||
|
||
|
||
@translate.command() | ||
def compile(): | ||
"""Compile all languages.""" | ||
if os.system('pybabel compile -d app/translations'): | ||
raise RuntimeError('compile command failed') | ||
def register(app): | ||
@app.cli.group() | ||
def translate(): | ||
"""Translation and localization commands.""" | ||
pass | ||
|
||
@translate.command() | ||
@click.argument('lang') | ||
def init(lang): | ||
"""Initialize a new language.""" | ||
if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): | ||
raise RuntimeError('extract command failed') | ||
if os.system( | ||
'pybabel init -i messages.pot -d app/translations -l ' + lang): | ||
raise RuntimeError('init command failed') | ||
os.remove('messages.pot') | ||
|
||
@translate.command() | ||
def update(): | ||
"""Update all languages.""" | ||
if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): | ||
raise RuntimeError('extract command failed') | ||
if os.system('pybabel update -i messages.pot -d app/translations'): | ||
raise RuntimeError('update command failed') | ||
os.remove('messages.pot') | ||
|
||
@translate.command() | ||
def compile(): | ||
"""Compile all languages.""" | ||
if os.system('pybabel compile -d app/translations'): | ||
raise RuntimeError('compile command failed') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from flask import Blueprint | ||
|
||
bp = Blueprint('errors', __name__) | ||
|
||
from app.errors import handlers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from flask import render_template | ||
from app import db | ||
from app.errors import bp | ||
|
||
|
||
@bp.app_errorhandler(404) | ||
def not_found_error(error): | ||
return render_template('errors/404.html'), 404 | ||
|
||
|
||
@bp.app_errorhandler(500) | ||
def internal_error(error): | ||
db.session.rollback() | ||
return render_template('errors/500.html'), 500 |
Oops, something went wrong.