Skip to content
Newer
Older
100644 209 lines (174 sloc) 7.12 KB
eeb84df Initial commit
Orf authored
1 from functools import wraps
2 import hashlib
3c6bd1d Added RSS feed generation
Orf authored
3 from flask import render_template, request, Response, Flask, flash, redirect, url_for, abort, jsonify, Response
eeb84df Initial commit
Orf authored
4 import re
5 from unicodedata import normalize
6 from flaskext.sqlalchemy import SQLAlchemy
7 import datetime
8 from unicodedata import normalize
34c6982 Removed models.py and moved the model into simple.py.
Orf authored
9 import markdown
eeb84df Initial commit
Orf authored
10
11 app = Flask(__name__)
12 app.config.from_object('settings')
13 db = SQLAlchemy(app)
14
15 _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
16
34c6982 Removed models.py and moved the model into simple.py.
Orf authored
17 class Post(db.Model):
18 __tablename__ = "posts"
19 id = db.Column(db.Integer, primary_key=True)
20 title = db.Column(db.String(), unique=True)
21 slug = db.Column(db.String(), unique=True)
22 text = db.Column(db.String(), default="")
23 draft = db.Column(db.Boolean(), index=True, default=True)
808529c Post views are now tracked, and when writing a post it is auto saved …
Orf authored
24 views = db.Column(db.Integer(), default=0)
34c6982 Removed models.py and moved the model into simple.py.
Orf authored
25 created_at = db.Column(db.DateTime, index=True)
26 updated_at = db.Column(db.DateTime)
27
28 def render_content(self):
29 return markdown.Markdown(extensions=['fenced_code'], output_format="html5", safe_mode=True).convert(self.text)
30
3797614 Now handles if the db has been created before
Orf authored
31 try:
32 db.create_all()
33 except Exception:
34 pass
b1a4d52 Database is auto created now. Also config fixes
Orf authored
35
eeb84df Initial commit
Orf authored
36 def requires_authentication(f):
37 @wraps(f)
38 def _auth_decorator(*args, **kwargs):
39 auth = request.authorization
40 if not auth or not (auth.username == app.config["ADMIN_USERNAME"]
41 and hashlib.md5(auth.password).hexdigest() == app.config["ADMIN_PASSWORD"]):
42 return Response("Could not authenticate you", 401, {"WWW-Authenticate":'Basic realm="Login Required"'})
43 return f(*args, **kwargs)
44
45 return _auth_decorator
46
47 @app.route("/")
48 def index():
49 page = request.args.get("page", 0, type=int)
d49de45 And removed the import models. Oops.
Orf authored
50 posts_master = db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.asc())
eeb84df Initial commit
Orf authored
51 posts_count = posts_master.count()
52
53 posts = posts_master.limit(app.config["POSTS_PER_PAGE"]).offset(page*app.config["POSTS_PER_PAGE"]).all()
54 is_more = posts_count > ((page*app.config["POSTS_PER_PAGE"]) + app.config["POSTS_PER_PAGE"])
55
56 return render_template("index.html", posts=posts, now=datetime.datetime.now(),
57 is_more=is_more, current_page=page)
58
59 @app.route("/<int:post_id>")
60 def view_post(post_id):
61 try:
d49de45 And removed the import models. Oops.
Orf authored
62 post = db.session.query(Post).filter_by(id=post_id, draft=False).one()
eeb84df Initial commit
Orf authored
63 except Exception:
64 return abort(404)
65
808529c Post views are now tracked, and when writing a post it is auto saved …
Orf authored
66 db.session.query(Post).filter_by(id=post_id).update({Post.views:Post.views+1})
67 db.session.commit()
68
eeb84df Initial commit
Orf authored
69 return render_template("view.html", post=post)
70
71 @app.route("/<slug>")
72 def view_post_slug(slug):
73 try:
d49de45 And removed the import models. Oops.
Orf authored
74 post = db.session.query(Post).filter_by(slug=slug,draft=False).one()
eeb84df Initial commit
Orf authored
75 except Exception:
76 return abort(404)
77
808529c Post views are now tracked, and when writing a post it is auto saved …
Orf authored
78 db.session.query(Post).filter_by(slug=slug).update({Post.views:Post.views+1})
79 db.session.commit()
eeb84df Initial commit
Orf authored
80
808529c Post views are now tracked, and when writing a post it is auto saved …
Orf authored
81 pid = request.args.get("pid", "0")
eeb84df Initial commit
Orf authored
82 return render_template("view.html", post=post, pid=pid)
83
84 @app.route("/new", methods=["POST", "GET"])
85 @requires_authentication
86 def new_post():
d49de45 And removed the import models. Oops.
Orf authored
87 post = Post()
eeb84df Initial commit
Orf authored
88 post.title = request.form.get("title","untitled")
89 post.slug = slugify(post.title)
90 post.created_at = datetime.datetime.now()
91 post.updated_at = datetime.datetime.now()
92
93 db.session.add(post)
94 db.session.commit()
95
96 return redirect(url_for("edit", id=post.id))
97
98 @app.route("/edit/<int:id>", methods=["GET","POST"])
99 @requires_authentication
100 def edit(id):
101 try:
d49de45 And removed the import models. Oops.
Orf authored
102 post = db.session.query(Post).filter_by(id=id).one()
eeb84df Initial commit
Orf authored
103 except Exception:
104 return abort(404)
105
106 if request.method == "GET":
107 return render_template("edit.html", post=post)
108 else:
109 title = request.form.get("post_title","")
110 text = request.form.get("post_content","")
111 post.title = title
112 post.slug = slugify(post.title)
113 post.text = text
114 post.updated_at = datetime.datetime.now()
115
116 if any(request.form.getlist("post_draft", type=int)):
117 post.draft = True
118 else:
119 post.draft = False
120
121 db.session.add(post)
122 db.session.commit()
123 return redirect(url_for("edit", id=id))
124
125 @app.route("/delete/<int:id>", methods=["GET","POST"])
126 @requires_authentication
127 def delete(id):
128 try:
d49de45 And removed the import models. Oops.
Orf authored
129 post = db.session.query(Post).filter_by(id=id).one()
eeb84df Initial commit
Orf authored
130 except Exception:
131 flash("Error deleting post ID %s"%id, category="error")
132 else:
133 db.session.delete(post)
134 db.session.commit()
135
136 return redirect(request.args.get("next","") or request.referrer or url_for('index'))
137
138 @app.route("/admin", methods=["GET", "POST"])
139 @requires_authentication
140 def admin():
d49de45 And removed the import models. Oops.
Orf authored
141 drafts = db.session.query(Post).filter_by(draft=True)\
142 .order_by(Post.created_at.desc()).all()
143 posts = db.session.query(Post).filter_by(draft=False)\
144 .order_by(Post.created_at.desc()).all()
eeb84df Initial commit
Orf authored
145 return render_template("admin.html", drafts=drafts, posts=posts)
146
147 @app.route("/admin/save/<int:id>", methods=["POST"])
148 @requires_authentication
149 def save_post(id):
150 try:
d49de45 And removed the import models. Oops.
Orf authored
151 post = db.session.query(Post).filter_by(id=id).one()
eeb84df Initial commit
Orf authored
152 except Exception:
153 return abort(404)
154
155 post.title = request.form.get("title","")
156 post.slug = slugify(post.title)
157 post.text = request.form.get("content", "")
158 post.updated_at = datetime.datetime.now()
159 db.session.add(post)
160 db.session.commit()
161 return jsonify(success=True)
162
163 @app.route("/preview/<int:id>")
164 @requires_authentication
165 def preview(id):
166 try:
d49de45 And removed the import models. Oops.
Orf authored
167 post = db.session.query(Post).filter_by(id=id).one()
eeb84df Initial commit
Orf authored
168 except Exception:
169 return abort(404)
170
171 return render_template("post_preview.html", post=post)
172
3c6bd1d Added RSS feed generation
Orf authored
173 @app.route("/posts.rss")
174 def feed():
175 def generate_feed():
176 yield '<?xml version="1.0" encoding="UTF-8"?>\n'
177 yield '<rss version="2.0">\n'
178 yield ' <channel>\n'
179 yield ' <title>%s</title>\n'%app.config["BLOG_TITLE"]
180 yield ' <description>%s</title>\n'%app.config["BLOG_TAGLINE"]
181 yield ' <link>%s</link>\n'%app.config["BLOG_URL"]
d49de45 And removed the import models. Oops.
Orf authored
182 for post in db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.desc()).all():
3c6bd1d Added RSS feed generation
Orf authored
183 yield " <item>\n"
184 yield " <title>%s</title>\n"%post.title
185 if post.text:
186 yield " <description>%s</description>\n"%post.render_content()
187 else:
188 yield " <description>No content</description>\n"
189 yield " <pubDate>%s</pubDate>\n"%post.created_at.strftime('%B %d, %Y')
190 yield " <link>%s</link>\n"%("%s/%s"%(app.config["BLOG_URL"], post.slug ))
191 yield " <guid>%s</guid>\n"%("%s/%s"%(app.config["BLOG_URL"], post.slug ))
192 yield " </item>\n"
193 yield " </channel>\n"
194 yield "</rss>"
195
196 return Response(generate_feed(), mimetype="application/rss+xml")
197
eeb84df Initial commit
Orf authored
198 def slugify(text, delim=u'-'):
199 """Generates an slightly worse ASCII-only slug."""
200 result = []
201 for word in _punct_re.split(text.lower()):
202 word = normalize('NFKD', unicode(word)).encode('ascii', 'ignore')
203 if word:
204 result.append(word)
205 return unicode(delim.join(result))
206
207
208 if __name__ == "__main__":
209 app.run()
Something went wrong with that request. Please try again.