-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathapp.py
137 lines (100 loc) · 3.47 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import os
from cloudinary.uploader import upload
from cloudinary.utils import cloudinary_url
from flask import Flask, render_template, redirect, url_for, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_gfm import Markdown
from werkzeug.routing import BaseConverter
from sqlalchemy.sql import func
from sqlalchemy import inspect
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get(
"DATABASE_URL",
"sqlite:////tmp/python_markdown_wiki_local.db"
)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
def create_tables_if_not_exists():
with app.app_context():
engine = db.get_engine()
inspector = inspect(engine)
if "topic" not in inspector.get_table_names():
db.create_all()
create_tables_if_not_exists()
markdown = Markdown(app)
class Topic(db.Model):
name = db.Column(db.String(32), primary_key=True)
body = db.Column(db.Text, nullable=True, default='')
modified_at = db.Column(db.DateTime, nullable=False,
server_default=func.now(), onupdate=func.now())
created_at = db.Column(db.DateTime, nullable=False,
server_default=func.now())
@property
def backlinks(self):
return Topic.query.filter(
Topic.body.like(f'%[[{self.name}]]%')
)
@classmethod
def find(cls, name):
topic = cls.query.get(name)
if not topic:
topic = cls(name, None)
db.session.add(topic)
db.session.commit()
return topic
def __init__(self, name, body):
self.name = name
self.body = body
def __repr__(self):
return f'<Topic {self.name}>'
class TopicConverter(BaseConverter):
def to_python(self, value):
return Topic.find(value)
def to_url(self, value):
return value.name
app.url_map.converters['Topic'] = TopicConverter
@app.template_filter('parse_link')
def parse_link(body):
import re
for word in re.findall(r"\[\[([^\]]+)\]\]", body):
body = body.replace(u'[[{0}]]'.format(word),
u'[{0}](/{0})'.format(word))
return body
@app.route("/")
def index():
if 'topic' in request.args:
return redirect(
url_for('topic', topic=Topic.find(request.args['topic']))
)
return redirect(url_for('topic', topic=Topic.find('README')))
@app.route("/<Topic:topic>", methods=["GET", "POST"])
def topic(topic):
if request.method == 'GET':
return render_template('base.html', topic=topic)
else:
topic.body = request.values.get('body')
db.session.commit()
return redirect(url_for('topic', topic=topic))
@app.route("/<Topic:topic>/backlinks")
def backlinks(topic):
return render_template('backlinks.html', topic=topic)
@app.route("/<Topic:topic>/keynote")
def keynote(topic):
return render_template('keynote.html', topic=topic)
@app.route("/<Topic:topic>/edit")
def edit(topic):
return render_template('edit.html', topic=topic)
@app.route('/images', methods=['POST'])
def upload_image():
result = None
if 'file' in request.files:
upload_result = upload(request.files['file'])
result = cloudinary_url(upload_result['public_id'])[0]
return jsonify(filename=result)
@app.template_filter('env')
def env(s):
return os.environ.get(s)
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app.debug = True
app.run(host='0.0.0.0', port=port)