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
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -116,4 +116,6 @@ dmypy.json
|
|||||||
|
|
||||||
|
|
||||||
# Personal things!
|
# Personal things!
|
||||||
setup_env.sh
|
web.env
|
||||||
|
db.env
|
||||||
|
dump.sql
|
||||||
|
|||||||
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@@ -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"]
|
||||||
2
db.env.example
Normal file
2
db.env.example
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
MYSQL_ROOT_PASSWORD=secret
|
||||||
|
MYSQL_DATABASE=db
|
||||||
21
docker-compose.yml
Normal file
21
docker-compose.yml
Normal file
@@ -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:
|
||||||
6
gunicorn.conf
Normal file
6
gunicorn.conf
Normal file
@@ -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
|
||||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Flask
|
||||||
|
Flask-SQLAlchemy
|
||||||
|
mysqlclient
|
||||||
|
gunicorn
|
||||||
|
markdown
|
||||||
6
run.py
Normal file
6
run.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from www import create_app
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', debug=True)
|
||||||
7
web.env.example
Normal file
7
web.env.example
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
DATABASE_URI=mysql://root:secret@db:3306/db
|
||||||
|
TRACK_MODIFICATIONS=False
|
||||||
|
|
||||||
|
USERNAME=admin
|
||||||
|
PASSWORD=secret
|
||||||
|
|
||||||
|
SECRET_KEY=1337
|
||||||
6
wsgi.py
6
wsgi.py
@@ -1,6 +0,0 @@
|
|||||||
from www import create_app
|
|
||||||
|
|
||||||
app = create_app()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run()
|
|
||||||
@@ -5,43 +5,41 @@ from flask import redirect, url_for, render_template
|
|||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__, instance_relative_config=True)
|
app = Flask(__name__, instance_relative_config=True)
|
||||||
|
|
||||||
app.config.from_mapping(
|
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('/')
|
@app.route('/')
|
||||||
def index():
|
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)
|
db.init_app(app)
|
||||||
|
|
||||||
from . import auth
|
from www import commands
|
||||||
|
commands.init_app(app)
|
||||||
|
|
||||||
|
from www import auth
|
||||||
app.register_blueprint(auth.bp)
|
app.register_blueprint(auth.bp)
|
||||||
|
|
||||||
from . import admin
|
from www import admin
|
||||||
app.register_blueprint(admin.bp)
|
app.register_blueprint(admin.bp)
|
||||||
|
|
||||||
from . import blog
|
from www import blog
|
||||||
app.register_blueprint(blog.bp)
|
app.register_blueprint(blog.bp)
|
||||||
|
|
||||||
from . import now
|
from www import now
|
||||||
app.register_blueprint(now.bp)
|
app.register_blueprint(now.bp)
|
||||||
|
|
||||||
from . import recommended
|
from www import recommended
|
||||||
app.register_blueprint(recommended.bp)
|
app.register_blueprint(recommended.bp)
|
||||||
|
|
||||||
from . import projects
|
from www import projects
|
||||||
app.register_blueprint(projects.bp)
|
app.register_blueprint(projects.bp)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
from www.auth import admin_required
|
||||||
|
|
||||||
bp = Blueprint('admin', __name__, url_prefix='/admin')
|
bp = Blueprint('admin', __name__, url_prefix='/admin')
|
||||||
|
|||||||
20
www/auth.py
20
www/auth.py
@@ -1,11 +1,12 @@
|
|||||||
import functools
|
import functools
|
||||||
|
|
||||||
from www.db import get_db
|
|
||||||
|
|
||||||
from werkzeug.exceptions import abort
|
from werkzeug.exceptions import abort
|
||||||
from werkzeug.security import check_password_hash
|
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')
|
bp = Blueprint('auth', __name__, url_prefix='/auth')
|
||||||
@@ -16,21 +17,18 @@ def login():
|
|||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
user = db.execute(
|
user = User.query.filter_by(username=username).first()
|
||||||
'SELECT * FROM users WHERE username = ?', (username,)
|
|
||||||
).fetchone()
|
|
||||||
|
|
||||||
if user is None:
|
if user is None:
|
||||||
error = 'Incorrect username.'
|
error = 'Incorrect username.'
|
||||||
elif not check_password_hash(user['password'], password):
|
elif not check_password_hash(user.password, password):
|
||||||
error = 'Incorrect password.'
|
error = 'Incorrect password.'
|
||||||
|
|
||||||
if error is None:
|
if error is None:
|
||||||
session.clear()
|
session.clear()
|
||||||
session['user_id'] = user['id']
|
session['user_id'] = user.id
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
flash(error)
|
flash(error)
|
||||||
@@ -49,9 +47,7 @@ def load_logged_in_user():
|
|||||||
if user_id is None:
|
if user_id is None:
|
||||||
g.user = None
|
g.user = None
|
||||||
else:
|
else:
|
||||||
g.user = get_db().execute(
|
g.user = User.query.get(user_id)
|
||||||
'SELECT * FROM users WHERE id = ?', (user_id,)
|
|
||||||
).fetchone()
|
|
||||||
|
|
||||||
def admin_required(view):
|
def admin_required(view):
|
||||||
@functools.wraps(view)
|
@functools.wraps(view)
|
||||||
|
|||||||
69
www/blog.py
69
www/blog.py
@@ -1,23 +1,16 @@
|
|||||||
from flask import (
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
||||||
Blueprint, flash, g, redirect, render_template, request, url_for
|
|
||||||
)
|
|
||||||
|
|
||||||
from werkzeug.exceptions import abort
|
from werkzeug.exceptions import abort
|
||||||
import markdown as md
|
import markdown as md
|
||||||
|
|
||||||
from www.db import get_db
|
from www.models import db, Post
|
||||||
from www.auth import admin_required
|
from www.auth import admin_required
|
||||||
|
|
||||||
bp = Blueprint('blog', __name__, url_prefix='/blog')
|
bp = Blueprint('blog', __name__, url_prefix='/blog')
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
db = get_db()
|
posts = Post.query.order_by(Post.created_at.desc()).all()
|
||||||
posts = db.execute(
|
|
||||||
'SELECT id, title, resume, created_at'
|
|
||||||
' FROM posts'
|
|
||||||
' ORDER BY created_at DESC'
|
|
||||||
).fetchall()
|
|
||||||
|
|
||||||
return render_template('blog/index.html', posts=posts)
|
return render_template('blog/index.html', posts=posts)
|
||||||
|
|
||||||
@@ -38,13 +31,10 @@ def create():
|
|||||||
if error is not None:
|
if error is not None:
|
||||||
flash(error)
|
flash(error)
|
||||||
else:
|
else:
|
||||||
db = get_db()
|
post = Post(title, markdown, html, resume)
|
||||||
db.execute(
|
db.session.add(post)
|
||||||
'INSERT INTO posts (title, markdown, html, resume)'
|
db.session.commit()
|
||||||
' VALUES (?, ?, ?, ?)',
|
|
||||||
(title, markdown, html, resume)
|
|
||||||
)
|
|
||||||
db.commit()
|
|
||||||
return redirect(url_for('blog.index'))
|
return redirect(url_for('blog.index'))
|
||||||
|
|
||||||
return render_template('blog/create.html')
|
return render_template('blog/create.html')
|
||||||
@@ -52,12 +42,7 @@ def create():
|
|||||||
@bp.route('/update/<int:id>', methods=('GET', 'POST'))
|
@bp.route('/update/<int:id>', methods=('GET', 'POST'))
|
||||||
@admin_required
|
@admin_required
|
||||||
def update(id):
|
def update(id):
|
||||||
post = get_db().execute(
|
post = Post.query.get(id)
|
||||||
'SELECT id, title, markdown, resume'
|
|
||||||
' FROM posts'
|
|
||||||
' WHERE id = ?',
|
|
||||||
(id,)
|
|
||||||
).fetchone()
|
|
||||||
|
|
||||||
if post is None:
|
if post is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
@@ -76,52 +61,34 @@ def update(id):
|
|||||||
if error is not None:
|
if error is not None:
|
||||||
flash(error)
|
flash(error)
|
||||||
else:
|
else:
|
||||||
db = get_db()
|
post.title = title
|
||||||
db.execute(
|
post.markdown = markdown
|
||||||
'UPDATE posts'
|
post.html = html
|
||||||
' SET title = ?, markdown = ?, html = ?, resume = ?'
|
post.resume = resume
|
||||||
' WHERE id = ?',
|
db.session.commit()
|
||||||
(title, markdown, html, resume, id)
|
|
||||||
)
|
|
||||||
db.commit()
|
|
||||||
return redirect(url_for('blog.index'))
|
return redirect(url_for('blog.index'))
|
||||||
|
|
||||||
return render_template('blog/update.html', post=post)
|
return render_template('blog/update.html', post=post)
|
||||||
|
|
||||||
@bp.route('/<int:id>')
|
@bp.route('/<int:id>')
|
||||||
def view(id):
|
def view(id):
|
||||||
post = get_db().execute(
|
post = Post.query.get(id)
|
||||||
'SELECT id, title, html'
|
|
||||||
' FROM posts'
|
|
||||||
' WHERE id = ?',
|
|
||||||
(id,)
|
|
||||||
).fetchone()
|
|
||||||
|
|
||||||
if post is None:
|
if post is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
else:
|
else:
|
||||||
return render_template('blog/view.html', post=post)
|
return render_template('blog/view.html', post=post)
|
||||||
|
|
||||||
@bp.route('/delete/<int:id>', methods=('GET', 'POST',))
|
@bp.route('/delete/<int:id>', methods=['POST'])
|
||||||
@admin_required
|
@admin_required
|
||||||
def delete(id):
|
def delete(id):
|
||||||
if request.method == 'GET':
|
post = Post.query.get(id)
|
||||||
abort(404)
|
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
post = db.execute(
|
|
||||||
'SELECT id'
|
|
||||||
' FROM posts'
|
|
||||||
' WHERE id = ?',
|
|
||||||
(id,)
|
|
||||||
).fetchone()
|
|
||||||
print(post)
|
|
||||||
|
|
||||||
if post is None:
|
if post is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
else:
|
else:
|
||||||
db.execute('DELETE FROM posts WHERE id = ?', (id,))
|
db.session.delete(post)
|
||||||
db.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('blog.index'))
|
return redirect(url_for('blog.index'))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
46
www/commands.py
Normal file
46
www/commands.py
Normal file
@@ -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)
|
||||||
73
www/db.py
73
www/db.py
@@ -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)
|
|
||||||
|
|
||||||
@@ -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."
|
|
||||||
);
|
|
||||||
53
www/models.py
Normal file
53
www/models.py
Normal file
@@ -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'<Post {self.title} {self.created_at}>'
|
||||||
|
|
||||||
|
|
||||||
|
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'<Now {self.created_at}>'
|
||||||
33
www/now.py
33
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
|
import markdown as md
|
||||||
|
|
||||||
from www.db import get_db
|
from flask import Blueprint, redirect, render_template, request, url_for
|
||||||
|
|
||||||
from www.auth import admin_required
|
from www.auth import admin_required
|
||||||
|
from www.models import db, Now
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint('now', __name__, url_prefix='/now')
|
bp = Blueprint('now', __name__, url_prefix='/now')
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
db = get_db()
|
now = Now.query.order_by(Now.created_at.desc()).first()
|
||||||
now = db.execute(
|
|
||||||
'SELECT html'
|
|
||||||
' FROM now'
|
|
||||||
).fetchone()
|
|
||||||
|
|
||||||
return render_template('now/now.html', now=now)
|
return render_template('now/now.html', now=now)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/update', methods=('GET', 'POST'))
|
@bp.route('/update', methods=('GET', 'POST'))
|
||||||
@admin_required
|
@admin_required
|
||||||
def update():
|
def update():
|
||||||
@@ -27,19 +23,12 @@ def update():
|
|||||||
markdown = request.form['markdown']
|
markdown = request.form['markdown']
|
||||||
html = parse_markdown(markdown)
|
html = parse_markdown(markdown)
|
||||||
|
|
||||||
db = get_db()
|
now = Now(markdown, html)
|
||||||
db.execute(
|
db.session.add(now)
|
||||||
'UPDATE now'
|
db.session.commit()
|
||||||
' SET markdown = ?, html = ?',
|
|
||||||
(markdown, html,)
|
|
||||||
)
|
|
||||||
db.commit()
|
|
||||||
return redirect(url_for('now.index'))
|
return redirect(url_for('now.index'))
|
||||||
|
|
||||||
now = get_db().execute(
|
now = Now.query.order_by(Now.created_at.desc()).first()
|
||||||
'SELECT id, markdown'
|
|
||||||
' FROM now'
|
|
||||||
).fetchone()
|
|
||||||
return render_template('now/update.html', now=now)
|
return render_template('now/update.html', now=now)
|
||||||
|
|
||||||
def parse_markdown(markdown):
|
def parse_markdown(markdown):
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
from flask import (
|
from flask import Blueprint, render_template
|
||||||
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
|
|
||||||
|
|
||||||
bp = Blueprint('projects', __name__, url_prefix='/projects')
|
bp = Blueprint('projects', __name__, url_prefix='/projects')
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('empty.html')
|
return render_template('empty.html')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
from flask import (
|
from flask import Blueprint, render_template
|
||||||
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
|
|
||||||
|
|
||||||
bp = Blueprint('recommended', __name__, url_prefix='/recommended')
|
bp = Blueprint('recommended', __name__, url_prefix='/recommended')
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('empty.html')
|
return render_template('empty.html')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 (
|
|
||||||
"",""
|
|
||||||
);
|
|
||||||
Reference in New Issue
Block a user