mirror of
https://github.com/shouptech/flask-tutorial.git
synced 2026-02-03 07:29:42 +00:00
use sqlalchemy
This commit is contained in:
parent
c4c170d53d
commit
c3a3eb30e2
6 changed files with 61 additions and 88 deletions
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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('/<int:id>/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'))
|
||||
|
|
|
|||
52
flaskr/db.py
52
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 '<User %r>' % 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 '<Post %r>' % self.title
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@
|
|||
<article class="post">
|
||||
<header>
|
||||
<div>
|
||||
<h1>{{ post['title'] }}</h1>
|
||||
<div class="about">by {{ post['username'] }} on {{ post['created'].strftime('%Y-%m-%d') }}</div>
|
||||
<h1>{{ post.title }}</h1>
|
||||
<div class="about">by {{ post.user.username }} on {{ post.created.strftime('%Y-%m-%d') }}</div>
|
||||
</div>
|
||||
{% if g.user['id'] == post['author_id'] %}
|
||||
<a class="action" href="{{ url_for('blog.update', id=post['id']) }}">Edit</a>
|
||||
{% if g.user.id == post.user_id %}
|
||||
<a class="action" href="{{ url_for('blog.update', id=post.id) }}">Edit</a>
|
||||
{% endif %}
|
||||
</header>
|
||||
<p class="body">{{ post['body'] }}</p>
|
||||
<p class="body">{{ post.body }}</p>
|
||||
</article>
|
||||
{% if not loop.last %}
|
||||
<hr>
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -8,5 +8,6 @@ setup(
|
|||
zip_safe=False,
|
||||
install_requires=[
|
||||
'flask',
|
||||
'flask_sqlalchemy',
|
||||
],
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue