diff --git a/flaskr/__init__.py b/flaskr/__init__.py index d3a431f..77b00ed 100644 --- a/flaskr/__init__.py +++ b/flaskr/__init__.py @@ -7,8 +7,11 @@ def create_app(test_config=None): # create and configure the app app = Flask(__name__, instance_relative_config=True) app.config.from_mapping( - DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'), - SECRET_KEY = os.environ.get("SECRET_KEY", default=None) + SECRET_KEY = os.environ.get("SECRET_KEY", default=None), + SQLALCHEMY_TRACK_MODIFICATIONS = os.environ.get( + "SQLALCHEMY_TRACK_MODIFICATIONS", default=False), + SQLALCHEMY_DATABASE_URI = os.environ.get( + "SQLALCHEMY_DATABASE_URI", default=None) ) if test_config is None: @@ -23,7 +26,6 @@ def create_app(test_config=None): os.makedirs(app.instance_path) except OSError: pass - # a simple page that says hello @app.route('/hello') def hello(): diff --git a/flaskr/auth.py b/flaskr/auth.py index b481433..704f3a3 100644 --- a/flaskr/auth.py +++ b/flaskr/auth.py @@ -5,7 +5,7 @@ from flask import ( ) from werkzeug.security import check_password_hash, generate_password_hash -from flaskr.db import get_db +from flaskr.db import db, User bp = Blueprint('auth', __name__, url_prefix='/auth') @@ -14,24 +14,18 @@ def register(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] - db = get_db() error = None if not username: error = 'Username is required.' elif not password: error = 'Password is required.' - elif db.execute( - 'SELECT id FROM user WHERE username = ?', (username,) - ).fetchone() is not None: + elif User.query.filter_by(username=username).first() is not None: error = 'User {} is already registered.'.format(username) - - if error is None: - db.execute( - 'INSERT INTO user (username, password) VALUES (?, ?)', - (username, generate_password_hash(password)) - ) - db.commit() + else: + db.session.add(User(username=username, + password=generate_password_hash(password))) + db.session.commit() return redirect(url_for('auth.login')) flash(error) @@ -43,20 +37,18 @@ def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] - db = get_db() error = None - user = db.execute( - 'SELECT * FROM user WHERE username = ?', (username,) - ).fetchone() + + user = User.query.filter_by(username=username).first() if user is None: error = 'Incorrect username.' - elif not check_password_hash(user['password'], password): + elif not check_password_hash(user.password, password): error = 'Incorrect password.' if error is None: session.clear() - session['user_id'] = user['id'] + session['user_id'] = user.id return redirect(url_for('index')) flash(error) @@ -70,9 +62,7 @@ def load_logged_in_user(): if user_id is None: g.user = None else: - g.user = get_db().execute( - 'SELECT * FROM user WHERE id = ?', (user_id,) - ).fetchone() + g.user = User.query.filter_by(id=user_id).first() @bp.route('/logout') def logout(): diff --git a/flaskr/blog.py b/flaskr/blog.py index 9094789..dcc431a 100644 --- a/flaskr/blog.py +++ b/flaskr/blog.py @@ -4,18 +4,13 @@ from flask import ( from werkzeug.exceptions import abort from flaskr.auth import login_required -from flaskr.db import get_db +from flaskr.db import db, Post, User bp = Blueprint('blog', __name__) @bp.route('/') def index(): - db = get_db() - posts = db.execute( - 'SELECT p.id, title, body, created, author_id, username' - ' FROM post p JOIN user u ON p.author_id = u.id' - ' ORDER BY created DESC' - ).fetchall() + posts = Post.query.join(User).order_by(Post.created.desc()).all() return render_template('blog/index.html', posts=posts) @bp.route('/create', methods=('GET', 'POST')) @@ -32,29 +27,21 @@ def create(): if error is not None: flash(error) else: - db = get_db() - db.execute( - 'INSERT INTO post (title, body, author_id)' - ' VALUES (?, ?, ?)', - (title, body, g.user['id']) - ) - db.commit() + db.session.add(Post(title=title, + body=body, + user_id=g.user.id)) + db.session.commit() return redirect(url_for('blog.index')) return render_template('blog/create.html') def get_post(id, check_author=True): - post = get_db().execute( - 'SELECT p.id, title, body, created, author_id, username' - ' FROM post p JOIN user u ON p.author_id = u.id' - ' WHERE p.id = ?', - (id,) - ).fetchone() + post = Post.query.filter_by(id=id).first() if post is None: abort(404, "Post id {0} doesn't exist.".format(id)) - if check_author and post['author_id'] != g.user['id']: + if check_author and post.user_id != g.user.id: abort(403) return post @@ -75,13 +62,10 @@ def update(id): if error is not None: flash(error) else: - db = get_db() - db.execute( - 'UPDATE post SET title = ?, body = ?' - ' WHERE id = ?', - (title, body, id) - ) - db.commit() + post = Post.query.filter_by(id=id).first() + post.title = title + post.body = body + db.session.commit() return redirect(url_for('blog.index')) return render_template('blog/update.html', post=post) @@ -89,8 +73,6 @@ def update(id): @bp.route('//delete', methods=('POST',)) @login_required def delete(id): - get_post(id) - db = get_db() - db.execute('DELETE FROM post WHERE id = ?', (id,)) - db.commit() + db.session.delete(get_post(id)) + db.session.commit() return redirect(url_for('blog.index')) diff --git a/flaskr/db.py b/flaskr/db.py index 44bab9e..fb85bfd 100644 --- a/flaskr/db.py +++ b/flaskr/db.py @@ -1,41 +1,39 @@ -import sqlite3 +from datetime import datetime import click from flask import current_app, g from flask.cli import with_appcontext +from flask_sqlalchemy import SQLAlchemy - -def get_db(): - if 'db' not in g: - g.db = sqlite3.connect( - current_app.config['DATABASE'], - detect_types=sqlite3.PARSE_DECLTYPES - ) - g.db.row_factory = sqlite3.Row - - return g.db - - -def close_db(e=None): - db = g.pop('db', None) - - if db is not None: - db.close() - -def init_db(): - db = get_db() - - with current_app.open_resource('schema.sql') as f: - db.executescript(f.read().decode('utf8')) - +db = SQLAlchemy() @click.command('init-db') @with_appcontext def init_db_command(): """Clear the existing data and create new tables.""" - init_db() + db.create_all() click.echo('Initialized the database.') def init_app(app): - app.teardown_appcontext(close_db) + db.init_app(app) # Initialize the sql alchemy database app.cli.add_command(init_db_command) + +# Model definitions +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.Text, nullable=False) + password = db.Column(db.Text, nullable=False) + posts = db.relationship('Post', backref='user', lazy=True) + + def __repr__(self): + return '' % self.username + +class Post(db.Model): + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + title = db.Column(db.Text, nullable=False) + body = db.Column(db.Text, nullable=False) + + def __repr__(self): + return '' % self.title diff --git a/flaskr/templates/blog/index.html b/flaskr/templates/blog/index.html index 3481b8e..cd9e629 100644 --- a/flaskr/templates/blog/index.html +++ b/flaskr/templates/blog/index.html @@ -12,14 +12,14 @@
-

{{ post['title'] }}

-
by {{ post['username'] }} on {{ post['created'].strftime('%Y-%m-%d') }}
+

{{ post.title }}

+
by {{ post.user.username }} on {{ post.created.strftime('%Y-%m-%d') }}
- {% if g.user['id'] == post['author_id'] %} - Edit + {% if g.user.id == post.user_id %} + Edit {% endif %}
-

{{ post['body'] }}

+

{{ post.body }}

{% if not loop.last %}
diff --git a/setup.py b/setup.py index 3912eaa..9cb397c 100644 --- a/setup.py +++ b/setup.py @@ -8,5 +8,6 @@ setup( zip_safe=False, install_requires=[ 'flask', + 'flask_sqlalchemy', ], )