More API
This commit is contained in:
parent
8547fdeece
commit
63001a7279
9 changed files with 85 additions and 15 deletions
|
|
@ -4,7 +4,7 @@ from sqlalchemy import create_engine, MetaData, Table, Column, Integer, \
|
|||
from sqlalchemy.orm import scoped_session, sessionmaker, backref, relation
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
from werkzeug import cached_property
|
||||
from werkzeug import cached_property, http_date
|
||||
|
||||
from flask import url_for
|
||||
from flask_website import config
|
||||
|
|
@ -32,6 +32,9 @@ class User(Model):
|
|||
self.name = name
|
||||
self.openid = openid
|
||||
|
||||
def to_json(self):
|
||||
return dict(name=self.name, is_admin=self.is_admin)
|
||||
|
||||
@property
|
||||
def is_admin(self):
|
||||
return self.openid in config.ADMINS
|
||||
|
|
@ -53,6 +56,9 @@ class Category(Model):
|
|||
self.name = name
|
||||
self.slug = '-'.join(name.split()).lower()
|
||||
|
||||
def to_json(self):
|
||||
return dict(name=self.name, slug=self.slug, count=self.count)
|
||||
|
||||
@cached_property
|
||||
def count(self):
|
||||
return self.snippets.count()
|
||||
|
|
@ -81,6 +87,14 @@ class Snippet(Model):
|
|||
self.category = category
|
||||
self.pub_date = datetime.utcnow()
|
||||
|
||||
def to_json(self):
|
||||
return dict(id=self.id, title=self.title,
|
||||
body=unicode(self.rendered_body),
|
||||
pub_date=http_date(self.pub_date),
|
||||
comments=[c.to_json() for c in self.comments],
|
||||
author=self.author.to_json(),
|
||||
category=self.category.slug)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return url_for('snippets.show', id=self.id)
|
||||
|
|
@ -110,6 +124,12 @@ class Comment(Model):
|
|||
self.text = text
|
||||
self.pub_date = datetime.utcnow()
|
||||
|
||||
def to_json(self):
|
||||
return dict(author=self.author.to_json(),
|
||||
title=self.title,
|
||||
pub_date=http_date(self.pub_date),
|
||||
text=unicode(self.rendered_text))
|
||||
|
||||
@property
|
||||
def rendered_text(self):
|
||||
from flask_website.utils import format_creole
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ class Extension(object):
|
|||
self.docs = docs
|
||||
self.website = website
|
||||
|
||||
def to_json(self):
|
||||
rv = vars(self).copy()
|
||||
rv['description'] = unicode(rv['description'])
|
||||
return rv
|
||||
|
||||
@property
|
||||
def pypi(self):
|
||||
return 'http://pypi.python.org/pypi/%s' % url_quote(self.name)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ class Project(object):
|
|||
if self.source is not None:
|
||||
return urlparse(self.source)[1]
|
||||
|
||||
def to_json(self):
|
||||
rv = vars(self).copy()
|
||||
rv['description'] = unicode(rv['description'])
|
||||
return rv
|
||||
|
||||
|
||||
projects = {
|
||||
'websites': [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import urllib2
|
|||
import time
|
||||
import threading
|
||||
from flask import json, Markup
|
||||
from werkzeug import url_encode, parse_date
|
||||
from werkzeug import url_encode, parse_date, http_date
|
||||
|
||||
|
||||
class SearchResult(object):
|
||||
|
|
@ -17,6 +17,12 @@ class SearchResult(object):
|
|||
self.type = result['metadata']['result_type']
|
||||
self.retweets = result['metadata'].get('recent_retweets') or 0
|
||||
|
||||
def to_json(self):
|
||||
rv = vars(self).copy()
|
||||
rv['pub_date'] = http_date(rv['pub_date'])
|
||||
rv['via'] = unicode(rv['via'])
|
||||
return rv
|
||||
|
||||
|
||||
class SearchQuery(object):
|
||||
fetch_timeout = 10
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ def split_lines_wrapping(text, width=74, threshold=82):
|
|||
return result
|
||||
|
||||
|
||||
def request_wants_json():
|
||||
return request.accept_mimetypes \
|
||||
.best_match(['application/json', 'text/html']) == 'application/json'
|
||||
|
||||
|
||||
def requires_login(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from flask import Module, render_template
|
||||
from flask import Module, render_template, jsonify
|
||||
from flask_website.twitter import flask_tweets
|
||||
from flask_website.utils import request_wants_json
|
||||
from flask_website.listings.projects import projects
|
||||
|
||||
mod = Module(__name__, url_prefix='/community')
|
||||
|
|
@ -17,6 +18,8 @@ def irc():
|
|||
|
||||
@mod.route('/twitter/')
|
||||
def twitter():
|
||||
if request_wants_json():
|
||||
return jsonify(tweets=[t.to_json() for t in flask_tweets])
|
||||
return render_template('community/twitter.html', tweets=flask_tweets)
|
||||
|
||||
|
||||
|
|
@ -27,6 +30,9 @@ def badges():
|
|||
|
||||
@mod.route('/poweredby/')
|
||||
def poweredby():
|
||||
if request_wants_json():
|
||||
return jsonify((k, [p.to_json() for p in v])
|
||||
for k, v in projects.iteritems())
|
||||
return render_template('community/poweredby.html', projects=projects)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
from flask import Module, render_template, jsonify, request
|
||||
from flask import Module, render_template, jsonify
|
||||
from flask_website.utils import request_wants_json
|
||||
from flask_website.listings.extensions import extensions
|
||||
|
||||
mod = Module(__name__, url_prefix='/extensions')
|
||||
|
||||
|
||||
def wants_json():
|
||||
return request.accept_mimetypes \
|
||||
.best_match(['application/json', 'text/html']) == 'application/json'
|
||||
|
||||
@mod.route('/')
|
||||
def index():
|
||||
if wants_json():
|
||||
return jsonify(extensions=map(vars, extensions))
|
||||
if request_wants_json():
|
||||
return jsonify(extensions=[ext.to_json() for ext in extensions])
|
||||
return render_template('extensions/index.html', extensions=extensions)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ from __future__ import with_statement
|
|||
import os
|
||||
from math import ceil
|
||||
from hashlib import md5
|
||||
from werkzeug import parse_date
|
||||
from werkzeug import parse_date, http_date
|
||||
from jinja2.utils import urlize
|
||||
from flask import Module, render_template, json, url_for, abort, Markup
|
||||
from flask_website.utils import split_lines_wrapping
|
||||
from flask import Module, render_template, json, url_for, abort, Markup, \
|
||||
jsonify
|
||||
from flask_website.utils import split_lines_wrapping, request_wants_json
|
||||
from flask_website import config
|
||||
|
||||
mod = Module(__name__, url_prefix='/mailinglist')
|
||||
|
|
@ -36,6 +37,12 @@ class Mail(object):
|
|||
result.append(urlize(line))
|
||||
return Markup(u'\n'.join(result))
|
||||
|
||||
def to_json(self):
|
||||
rv = vars(self).copy()
|
||||
rv['date'] = http_date(rv['date'])
|
||||
rv['children'] = [c.to_json() for c in rv['children']]
|
||||
return rv
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return md5(self.msgid.encode('utf-8')).hexdigest()
|
||||
|
|
@ -72,6 +79,13 @@ class Thread(object):
|
|||
month=self.date.month, day=self.date.day,
|
||||
slug=self.slug)
|
||||
|
||||
def to_json(self):
|
||||
rv = vars(self).copy()
|
||||
rv['date'] = http_date(rv['date'])
|
||||
if 'root' in rv:
|
||||
rv['root'] = rv['root'].to_json()
|
||||
return rv
|
||||
|
||||
|
||||
@mod.route('/')
|
||||
def index():
|
||||
|
|
@ -87,6 +101,10 @@ def archive(page):
|
|||
if page != 1 and not threads:
|
||||
abort(404)
|
||||
page_count = int(ceil(len(all_threads) // float(config.THREADS_PER_PAGE)))
|
||||
if request_wants_json():
|
||||
return jsonify(offset=offset,
|
||||
total=len(all_threads),
|
||||
threads=[x.to_json() for x in threads])
|
||||
return render_template('mailinglist/archive.html',
|
||||
page_count=page_count, page=page, threads=threads)
|
||||
|
||||
|
|
@ -96,4 +114,6 @@ def show_thread(year, month, day, slug):
|
|||
thread = Thread.get(year, month, day, slug)
|
||||
if thread is None:
|
||||
abort(404)
|
||||
if request_wants_json():
|
||||
return jsonify(thread=thread.to_json())
|
||||
return render_template('mailinglist/show_thread.html', thread=thread)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from urlparse import urljoin
|
||||
from flask import Module, render_template, request, flash, abort, redirect, \
|
||||
g, url_for
|
||||
g, url_for, jsonify
|
||||
from werkzeug.contrib.atom import AtomFeed
|
||||
from flask_website.utils import requires_login, requires_admin, format_creole
|
||||
from flask_website.utils import requires_login, requires_admin, \
|
||||
format_creole, request_wants_json
|
||||
from flask_website.database import Category, Snippet, Comment, db_session
|
||||
|
||||
mod = Module(__name__, url_prefix='/snippets')
|
||||
|
|
@ -52,6 +53,8 @@ def show(id):
|
|||
snippet = Snippet.query.get(id)
|
||||
if snippet is None:
|
||||
abort(404)
|
||||
if request_wants_json():
|
||||
return jsonify(snippet=snippet.to_json())
|
||||
if request.method == 'POST':
|
||||
title = request.form['title']
|
||||
text = request.form['text']
|
||||
|
|
@ -140,6 +143,9 @@ def category(slug):
|
|||
if category is None:
|
||||
abort(404)
|
||||
snippets = category.snippets.order_by(Snippet.title).all()
|
||||
if request_wants_json():
|
||||
return jsonify(category=category.to_json(),
|
||||
snippets=[s.id for s in snippets])
|
||||
return render_template('snippets/category.html', category=category,
|
||||
snippets=snippets)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue