From c9ffcb8dcac61ffb18a427f393ea00a3b3a2bfd4 Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Fri, 15 Mar 2019 03:16:59 -0300 Subject: [PATCH] Todo se fue a docker igual que el otro repo Decidi pasar todo esto a docker igual para tener todo ahi, parece mas ordenado y mas facil de mantener en mi servidor de paso tambien hice el trabajo de pasar los modelos a sqlalchemy para usar mysql :3 --- .gitignore | 4 ++- Dockerfile | 16 ++++++++++ db.env.example | 2 ++ docker-compose.yml | 21 +++++++++++++ dump.sql | 27 +++++++++++++++++ gunicorn.conf | 6 ++++ requirements.txt | 5 ++++ run.py | 6 ++++ web.env.example | 7 +++++ wsgi.py | 6 ---- www/__init__.py | 34 ++++++++++----------- www/admin.py | 3 +- www/auth.py | 20 +++++-------- www/blog.py | 75 +++++++++++++--------------------------------- www/commands.py | 46 ++++++++++++++++++++++++++++ www/db.py | 73 -------------------------------------------- www/dummy.sql | 25 ---------------- www/models.py | 53 ++++++++++++++++++++++++++++++++ www/now.py | 37 ++++++++--------------- www/projects.py | 12 +------- www/recommended.py | 11 +------ www/schema.sql | 28 ----------------- 22 files changed, 253 insertions(+), 264 deletions(-) create mode 100644 Dockerfile create mode 100644 db.env.example create mode 100644 docker-compose.yml create mode 100644 dump.sql create mode 100644 gunicorn.conf create mode 100644 requirements.txt create mode 100644 run.py create mode 100644 web.env.example delete mode 100644 wsgi.py create mode 100644 www/commands.py delete mode 100644 www/db.py delete mode 100644 www/dummy.sql create mode 100644 www/models.py delete mode 100644 www/schema.sql diff --git a/.gitignore b/.gitignore index 19c746c..2a1cdfd 100644 --- a/.gitignore +++ b/.gitignore @@ -116,4 +116,6 @@ dmypy.json # Personal things! -setup_env.sh +web.env +db.env +dump.sql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ecc9d76 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:alpine + +RUN mkdir /app +COPY requirements.txt gunicorn.conf run.py /app/ +COPY www/ /app/www +ENV FLASK_APP=www +WORKDIR /app +RUN apk add mariadb-connector-c-dev gcc musl-dev +RUN pip install --no-cache-dir -r requirements.txt +RUN apk del gcc musl-dev + +ENV GUNICORN_WORKERS 2 +ENV GUNICORN_BIND 0.0.0.0:8081 + +EXPOSE 8081 +CMD ["gunicorn", "--config", "gunicorn.conf", "run:app"] diff --git a/db.env.example b/db.env.example new file mode 100644 index 0000000..ff92198 --- /dev/null +++ b/db.env.example @@ -0,0 +1,2 @@ +MYSQL_ROOT_PASSWORD=secret +MYSQL_DATABASE=db diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..39b44c3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3' +services: + web: + build: . + ports: + - "8081:8081" + volumes: + - ./www:/app/www + depends_on: + - db + env_file: + - web.env + command: "gunicorn --config gunicorn.conf run:app" + db: + image: mariadb + volumes: + - dbdata:/var/lib/mysql + env_file: + - db.env +volumes: + dbdata: diff --git a/dump.sql b/dump.sql new file mode 100644 index 0000000..b46fd90 --- /dev/null +++ b/dump.sql @@ -0,0 +1,27 @@ +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + markdown TEXT NOT NULL, + html TEXT NOT NULL, + resume TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); +CREATE TABLE now ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + markdown TEXT NOT NULL, + html TEXT NOT NULL +); +INSERT INTO now VALUES(1,replace(replace('### Esta es mi pagina /now.\r\n\r\nTome esta idea del señor [Derek Sivers](https://sivers.org/now), con quien me encontré tras estar buscando varias paginas personales en posts de [dev.to](https://dev.to/) y [reddit](https://www.reddit.com/r/web_design/comments/6glc6i/best_ridiculously_simple_portfolio_sites/), resulta que varias de ellas tenían esta sección y me pareció lo suficientemente interesante como para añadirla aquí.\r\n\r\n__Actualizada en 14/02/2018__\r\n\r\n#### Programación:\r\n\r\n- Estoy haciendo esta pagina nuevamente, cometí un grave error al intentarlo hacer 100% html estático, fue un sufrimiento manejar los links y todo eso, así que me decante por hacerla con Flask y SQLite para mantener todo correcto y poder hacerla mínimamente dinámica en su interior, como por ejemplo, ahora hice un pequeño panel de administración en el cual puedo subir posts para el blog y actualizar el now utilizando Markdown, es una maravilla!, ahora le quiero agregar uno para añadir recomendaciones y poder agregar links a los proyectos que e hecho.\r\n- Estoy haciendo una aplicación para la contabilidad de las cajas diarias de nuestro restaurant familiar, es una pequeña aplicación en Java y SQLite nuevamente, tenia que ser una base de dato embebida dado que ya que en los computadores en que se utiliza hay un servidor MySQL, el cual es version 4.3 si no me equivoco, por lo que seria un problema que no quiero solucionar, y a costa de esto tuve que mas o menos hacerme un "ORM" para poder comunicarme con SQLite porque parece que Java no se lleva muy bien con esta base de datos e Hibernate no pareciera tener soporte.\r\n\r\n#### Aprendiendo:\r\n\r\n- Primeramente ahora estoy metido con java e intento hacer un software lo mas correcto posible por lo que estoy intentando aprender un poco de patrones y utilizarlos en la vida real.\r\n- Flask! Con el cual estoy haciendo esta pagina, me gusta bastante, es conciso y limpio cuando lo comparo con lo que hacia con PHP y Laravel, al menos a mi parecer, supongo que gracias a que es Python3.\r\n- Realice un cambio de universidad desde la UFRO a la Inacap por motivos varios. Por lo que ahora estoy en una universidad nueva y tristemente pareciera que quede un semestre mas atras de lo que me hubiese tocado, pero hay que salir adelante y aprovechar la oportunidad de repasar cosas que quizas estoy pasando por alto.\r\n\r\n#### Libros:\r\n\r\n__(Aviso! Soy un muy mal lector, por lo que estos libros probablemente se mantendrán aquí un largo tiempo antes que los termine)__\r\n\r\n- En Las Montañas de la Locura, H.P Lovecraft. Este esta en un compilado junto a "Los Sueños en la Casa de la Bruja" y "La Sombra Sobre Innsmouth" los cuales ya termine y debo admitir me encantaron.\r\n- IT, Stephen King. Este lo tengo en mi velador todas las noches, lo veo y no lo leo, no me doy el tiempo de tomarlo y continuarlo, llevo un tercio de el y aun no me e dado el tiempo de continuar.\r\n- Don Quijote De La Mancha, Miguel de Cervantes. Bien loco, me he reído bastante mientras e ido leyendo, aunque debo decir que lo tengo tirado y no lo e avanzado, debería.\r\n\r\n\r\n','\r',char(13)),'\n',char(10)),replace('

Esta es mi pagina /now.

\n

Tome esta idea del señor Derek Sivers, con quien me encontré tras estar buscando varias paginas personales en posts de dev.to y reddit, resulta que varias de ellas tenían esta sección y me pareció lo suficientemente interesante como para añadirla aquí.

\n

Actualizada en 14/02/2018

\n

Programación:

\n\n

Aprendiendo:

\n\n

Libros:

\n

(Aviso! Soy un muy mal lector, por lo que estos libros probablemente se mantendrán aquí un largo tiempo antes que los termine)

\n','\n',char(10))); +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + password TEXT NOT NULL +); +INSERT INTO users VALUES(1,'ryuuji','pbkdf2:sha256:50000$0fDBIsdx$b1866621bed6c2405d54c8cc617203f6fa51bc2a68b03c7cb57a49c28ebe1e9e'); +DELETE FROM sqlite_sequence; +INSERT INTO sqlite_sequence VALUES('now',1); +INSERT INTO sqlite_sequence VALUES('users',1); +INSERT INTO sqlite_sequence VALUES('posts',1); +COMMIT; diff --git a/gunicorn.conf b/gunicorn.conf new file mode 100644 index 0000000..b1bd733 --- /dev/null +++ b/gunicorn.conf @@ -0,0 +1,6 @@ +import os + +for k,v in os.environ.items(): + if k.startswith("GUNICORN_"): + key = k.split('_', 1)[1].lower() + locals()[key] = v diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d01b541 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Flask +Flask-SQLAlchemy +mysqlclient +gunicorn +markdown diff --git a/run.py b/run.py new file mode 100644 index 0000000..3045cd9 --- /dev/null +++ b/run.py @@ -0,0 +1,6 @@ +from www import create_app + +app = create_app() + +if __name__ == '__main__': + app.run(host='0.0.0.0', debug=True) diff --git a/web.env.example b/web.env.example new file mode 100644 index 0000000..000a67d --- /dev/null +++ b/web.env.example @@ -0,0 +1,7 @@ +DATABASE_URI=mysql://root:secret@db:3306/db +TRACK_MODIFICATIONS=False + +USERNAME=admin +PASSWORD=secret + +SECRET_KEY=1337 diff --git a/wsgi.py b/wsgi.py deleted file mode 100644 index e9762e6..0000000 --- a/wsgi.py +++ /dev/null @@ -1,6 +0,0 @@ -from www import create_app - -app = create_app() - -if __name__ == "__main__": - app.run() diff --git a/www/__init__.py b/www/__init__.py index 34765d6..ad09396 100644 --- a/www/__init__.py +++ b/www/__init__.py @@ -5,43 +5,41 @@ from flask import redirect, url_for, render_template def create_app(): app = Flask(__name__, instance_relative_config=True) - app.config.from_mapping( - DATABASE=os.path.join(app.instance_path, 'www.sqlite'), + SQLALCHEMY_DATABASE_URI=os.environ.get("DATABASE_URI"), + SQLALCHEMY_TRACK_MODIFICATIONS=os.environ.get("TRACK_MODIFICATIONS"), + USERNAME=os.environ.get("USERNAME"), + PASSWORD=os.environ.get("PASSWORD"), + SECRET_KEY=os.environ.get("SECRET_KEY") ) - app.config.from_pyfile('config.py', silent=True) - - try: - os.makedirs(app.instance_path) - except OSError: - pass - @app.route('/') def index(): - return redirect(url_for('blog.index')) + return redirect(url_for('blog.index')) - from . import db + from www.models import db db.init_app(app) - from . import auth + from www import commands + commands.init_app(app) + + from www import auth app.register_blueprint(auth.bp) - from . import admin + from www import admin app.register_blueprint(admin.bp) - from . import blog + from www import blog app.register_blueprint(blog.bp) - from . import now + from www import now app.register_blueprint(now.bp) - from . import recommended + from www import recommended app.register_blueprint(recommended.bp) - from . import projects + from www import projects app.register_blueprint(projects.bp) return app - diff --git a/www/admin.py b/www/admin.py index 828624f..849431b 100644 --- a/www/admin.py +++ b/www/admin.py @@ -1,6 +1,5 @@ -from flask import Blueprint, flash, g, redirect, render_template, request, session, url_for +from flask import Blueprint, render_template -from www.db import get_db from www.auth import admin_required bp = Blueprint('admin', __name__, url_prefix='/admin') diff --git a/www/auth.py b/www/auth.py index a3631e4..a078d40 100644 --- a/www/auth.py +++ b/www/auth.py @@ -1,11 +1,12 @@ import functools -from www.db import get_db - from werkzeug.exceptions import abort from werkzeug.security import check_password_hash -from flask import Blueprint, request, flash, render_template, session, g, redirect, url_for +from flask import Blueprint, render_template, request, session +from flask import url_for, flash, redirect, g + +from www.models import User bp = Blueprint('auth', __name__, url_prefix='/auth') @@ -16,21 +17,18 @@ def login(): username = request.form['username'] password = request.form['password'] - db = get_db() error = None - user = db.execute( - 'SELECT * FROM users 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) @@ -49,9 +47,7 @@ def load_logged_in_user(): if user_id is None: g.user = None else: - g.user = get_db().execute( - 'SELECT * FROM users WHERE id = ?', (user_id,) - ).fetchone() + g.user = User.query.get(user_id) def admin_required(view): @functools.wraps(view) diff --git a/www/blog.py b/www/blog.py index be86d31..0a286b4 100644 --- a/www/blog.py +++ b/www/blog.py @@ -1,23 +1,16 @@ -from flask import ( - Blueprint, flash, g, redirect, render_template, request, url_for -) +from flask import Blueprint, flash, redirect, render_template, request, url_for from werkzeug.exceptions import abort import markdown as md -from www.db import get_db -from www.auth import admin_required +from www.models import db, Post +from www.auth import admin_required bp = Blueprint('blog', __name__, url_prefix='/blog') @bp.route('/') def index(): - db = get_db() - posts = db.execute( - 'SELECT id, title, resume, created_at' - ' FROM posts' - ' ORDER BY created_at DESC' - ).fetchall() + posts = Post.query.order_by(Post.created_at.desc()).all() return render_template('blog/index.html', posts=posts) @@ -38,13 +31,10 @@ def create(): if error is not None: flash(error) else: - db = get_db() - db.execute( - 'INSERT INTO posts (title, markdown, html, resume)' - ' VALUES (?, ?, ?, ?)', - (title, markdown, html, resume) - ) - db.commit() + post = Post(title, markdown, html, resume) + db.session.add(post) + db.session.commit() + return redirect(url_for('blog.index')) return render_template('blog/create.html') @@ -52,12 +42,7 @@ def create(): @bp.route('/update/', methods=('GET', 'POST')) @admin_required def update(id): - post = get_db().execute( - 'SELECT id, title, markdown, resume' - ' FROM posts' - ' WHERE id = ?', - (id,) - ).fetchone() + post = Post.query.get(id) if post is None: abort(404) @@ -76,55 +61,37 @@ def update(id): if error is not None: flash(error) else: - db = get_db() - db.execute( - 'UPDATE posts' - ' SET title = ?, markdown = ?, html = ?, resume = ?' - ' WHERE id = ?', - (title, markdown, html, resume, id) - ) - db.commit() + post.title = title + post.markdown = markdown + post.html = html + post.resume = resume + db.session.commit() return redirect(url_for('blog.index')) return render_template('blog/update.html', post=post) @bp.route('/') def view(id): - post = get_db().execute( - 'SELECT id, title, html' - ' FROM posts' - ' WHERE id = ?', - (id,) - ).fetchone() - + post = Post.query.get(id) + if post is None: abort(404) else: return render_template('blog/view.html', post=post) -@bp.route('/delete/', methods=('GET', 'POST',)) +@bp.route('/delete/', methods=['POST']) @admin_required def delete(id): - if request.method == 'GET': - abort(404) + post = Post.query.get(id) - db = get_db() - post = db.execute( - 'SELECT id' - ' FROM posts' - ' WHERE id = ?', - (id,) - ).fetchone() - print(post) - if post is None: abort(404) else: - db.execute('DELETE FROM posts WHERE id = ?', (id,)) - db.commit() + db.session.delete(post) + db.session.commit() return redirect(url_for('blog.index')) def parse_markdown(markdown): - html = md.markdown(markdown) + html = md.markdown(markdown) return html diff --git a/www/commands.py b/www/commands.py new file mode 100644 index 0000000..11aa410 --- /dev/null +++ b/www/commands.py @@ -0,0 +1,46 @@ +import click + +from flask import current_app +from flask.cli import with_appcontext + +from werkzeug.security import generate_password_hash + +from www.models import db, User, Now + + +def init_db(): + db.create_all() + + +def generate_admin(): + username = current_app.config['USERNAME'] + + if User.query.filter_by(username=username).first() is None: + password = current_app.config['PASSWORD'] + + user = User(username, generate_password_hash(password)) + db.session.add(user) + db.session.commit() + +def generate_base_now(): + now = Now.query.first() + if now is None: + now = Now('', '') + db.session.add(now) + db.session.commit() + + +@click.command('init-db') +@with_appcontext +def init_db_command(): + """ + Creates and initializes the db with the necesary data + If the db existed previously, it keeps it and his data + """ + init_db() + generate_admin() + generate_base_now() + + +def init_app(app): + app.cli.add_command(init_db_command) diff --git a/www/db.py b/www/db.py deleted file mode 100644 index e6eae5e..0000000 --- a/www/db.py +++ /dev/null @@ -1,73 +0,0 @@ -import sqlite3 -import click - -from flask import current_app, g -from flask.cli import with_appcontext -from werkzeug.security import generate_password_hash - -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')) - -def fill_with_dummy(): - db = get_db() - - with current_app.open_resource('dummy.sql') as f: - db.executescript(f.read().decode('utf8')) - -def generate_admin(): - db = get_db() - username = current_app.config['USERNAME'] - password = current_app.config['PASSWORD'] - - db.execute( - 'INSERT INTO users (username, password) VALUES (?, ?)', - (username, generate_password_hash(password)) - ) - db.commit() - -@click.command('init-db') -@with_appcontext -def init_db_command(): - """Initializes the schema of the database""" - init_db() - click.echo('Initialized the database') - -@click.command('fill-with-dummy') -@with_appcontext -def fill_with_dummy_command(): - """Adds dummy data to the existing database""" - fill_with_dummy() - click.echo('Database filled with dummy data') - -@click.command('generate-admin') -@with_appcontext -def generate_admin_command(): - """Creates the admin account to be used""" - generate_admin() - click.echo('Created admin') - - -def init_app(app): - app.teardown_appcontext(close_db) - app.cli.add_command(init_db_command) - app.cli.add_command(fill_with_dummy_command) - app.cli.add_command(generate_admin_command) - diff --git a/www/dummy.sql b/www/dummy.sql deleted file mode 100644 index 6ca3bb3..0000000 --- a/www/dummy.sql +++ /dev/null @@ -1,25 +0,0 @@ -INSERT INTO posts (title, markdown, html, resume) values -( - "Excepturi et debitis explicabo occaecati", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Enim unde ut eaque vero saepe ut. Iure culpa modi ipsam maxime aliquid sed officiis. Consequatur minima quaerat molestias laudantium aut. Quia voluptas sint accusantium architecto." -), -( - "Excepturi et debitis explicabo occaecati", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Enim unde ut eaque vero saepe ut. Iure culpa modi ipsam maxime aliquid sed officiis. Consequatur minima quaerat molestias laudantium aut. Quia voluptas sint accusantium architecto." -), -( - "Excepturi et debitis explicabo occaecati", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Enim unde ut eaque vero saepe ut. Iure culpa modi ipsam maxime aliquid sed officiis. Consequatur minima quaerat molestias laudantium aut. Quia voluptas sint accusantium architecto." -), -( - "Excepturi et debitis explicabo occaecati", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Sit necessitatibus quibusdam autem facere tempore quibusdam assumenda. Quo sit asperiores earum beatae unde reiciendis perspiciatis. Blanditiis natus ex similique possimus optio veritatis.", - "Enim unde ut eaque vero saepe ut. Iure culpa modi ipsam maxime aliquid sed officiis. Consequatur minima quaerat molestias laudantium aut. Quia voluptas sint accusantium architecto." -); diff --git a/www/models.py b/www/models.py new file mode 100644 index 0000000..7d73c48 --- /dev/null +++ b/www/models.py @@ -0,0 +1,53 @@ +from datetime import datetime +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() + +class User(db.Model): + __tablename__ = 'users' + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(255), unique=True, nullable=False) + password = db.Column(db.String(255), nullable=False) + + def __init__(self, username=None, password=None): + self.username = username + self.password = password + + def __repr__(self): + return f'User {self.username}>' + + +class Post(db.Model): + __tablename__ = 'posts' + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.Text, nullable=False) + markdown = db.Column(db.Text, nullable=False) + html = db.Column(db.Text, nullable=False) + resume = db.Column(db.Text, nullable=False) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __init__(self, title=None, markdown=None, html=None, resume=None): + self.title = title + self.markdown = markdown + self.html = html + self.resume = resume + + + def __repr__(self): + return f'' + + +class Now(db.Model): + __tablename__ = 'nows' + id = db.Column(db.Integer, primary_key=True) + markdown = db.Column(db.Text, nullable=False) + html = db.Column(db.Text, nullable=False) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __init__(self, markdown=None, html=None): + self.markdown = markdown + self.html = html + + + def __repr__(self): + return f'' diff --git a/www/now.py b/www/now.py index 4c2a4ad..b16875d 100644 --- a/www/now.py +++ b/www/now.py @@ -1,25 +1,21 @@ -from flask import ( - Blueprint, flash, g, redirect, render_template, request, url_for -) - -from werkzeug.exceptions import abort import markdown as md -from www.db import get_db -from www.auth import admin_required +from flask import Blueprint, redirect, render_template, request, url_for + +from www.auth import admin_required +from www.models import db, Now + bp = Blueprint('now', __name__, url_prefix='/now') + @bp.route('/') def index(): - db = get_db() - now = db.execute( - 'SELECT html' - ' FROM now' - ).fetchone() + now = Now.query.order_by(Now.created_at.desc()).first() return render_template('now/now.html', now=now) + @bp.route('/update', methods=('GET', 'POST')) @admin_required def update(): @@ -27,21 +23,14 @@ def update(): markdown = request.form['markdown'] html = parse_markdown(markdown) - db = get_db() - db.execute( - 'UPDATE now' - ' SET markdown = ?, html = ?', - (markdown, html,) - ) - db.commit() + now = Now(markdown, html) + db.session.add(now) + db.session.commit() return redirect(url_for('now.index')) - now = get_db().execute( - 'SELECT id, markdown' - ' FROM now' - ).fetchone() + now = Now.query.order_by(Now.created_at.desc()).first() return render_template('now/update.html', now=now) def parse_markdown(markdown): - html = md.markdown(markdown) + html = md.markdown(markdown) return html diff --git a/www/projects.py b/www/projects.py index 5af750f..8301b3f 100644 --- a/www/projects.py +++ b/www/projects.py @@ -1,17 +1,7 @@ -from flask import ( - Blueprint, flash, g, redirect, render_template, request, url_for -) - -from werkzeug.exceptions import abort -import markdown as md - -from www.db import get_db -from www.auth import admin_required +from flask import Blueprint, render_template bp = Blueprint('projects', __name__, url_prefix='/projects') @bp.route('/') def index(): return render_template('empty.html') - - diff --git a/www/recommended.py b/www/recommended.py index 59b73ac..0c3647c 100644 --- a/www/recommended.py +++ b/www/recommended.py @@ -1,17 +1,8 @@ -from flask import ( - Blueprint, flash, g, redirect, render_template, request, url_for -) +from flask import Blueprint, render_template -from werkzeug.exceptions import abort -import markdown as md - -from www.db import get_db -from www.auth import admin_required bp = Blueprint('recommended', __name__, url_prefix='/recommended') @bp.route('/') def index(): return render_template('empty.html') - - diff --git a/www/schema.sql b/www/schema.sql deleted file mode 100644 index 21cf560..0000000 --- a/www/schema.sql +++ /dev/null @@ -1,28 +0,0 @@ -DROP TABLE IF EXISTS posts; -DROP TABLE IF EXISTS now; -DROP TABLE IF EXISTS users; - -CREATE TABLE posts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - title TEXT NOT NULL, - markdown TEXT NOT NULL, - html TEXT NOT NULL, - resume TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP -); - -CREATE TABLE now ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - markdown TEXT NOT NULL, - html TEXT NOT NULL -); - -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - password TEXT NOT NULL -); - -INSERT INTO now (markdown, html) VALUES ( - "","" -);