Welcome...
to the inaugural meeting of Chippenham Tech Chat...
Meetup Details
Will be hosted once a month at Mango/Scisys - Methuen Park
Presentations on various topics. If you're inter...
Lightweight Web Frameworks
Jonathan Holloway
jholloway@mango-solutions.com
twitter: jph98
Overview
● A brief history of web applications
● Past experience
● An overview of lightweight web frameworks
● An introduc...
Web Frameworks - A Brief History
● CGI and Perl - circa 1993
● PHP, Coldfusion - circa 1995
● ASP - circa 1998
● JSP and S...
261 !
* at least
Used Java Servlets and JSP around 1999/2000.
First introduction - somewhat painful.
Then discovered Struts in 2001/2002 (p...
Broken down into language (approx)
91 33 31 40
14 22 23 7
Past Experience - Post Java
Then looked at PHP for doing more lightweight
work. Used CakePHP 1.x then looked at
CodeIgnite...
Past Experience - First One Pager
Then ended up building a rich client interface in
Google Web Toolkit 1.x
Then around 200...
Flask - Python
Really?
Here's what we would have have done back in
the day with Apache Struts...
1. Setup web.xml
2. Created an index.jsp to forward on to my app
3. Setup struts-config.xml and added a form
and action ma...
5. Setup my forward on success
6. Put all this in a predefined folder structure
7. Package it all up into a war file
8. De...
then....
9. Fix the stupid errors
10. Deploy again and see Hello World in my
browser. Maybe.
easy...
Others?
There's others !!
There's a bunch of other lightweight web
frameworks in various languages:
● Flask - Python
● Nancy - .NE...
Web Framework Taxonomy
Sinatra, Flask, Berliner, Dancer, Ratpack, Nancy
[Micro Frameworks]
Rails, Django
[Lightweight Fram...
Sinatra - Ruby
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
get '/' do
'<b>Hello, world!</b>'
end
Nancy - dot NET
public class SampleModule : Nancy.
NancyModule
{
public SampleModule()
{
Get["/"] = _ => "Hello
World!";
}...
Ratpack - Groovy
get("/helloworld") {
"Hello, World!"
}
Berliner - Coffeescript
app = require 'berliner'
app.get '/', -> 'Hello, world!'
app.run 4567
Properties of such frameworks?
● Minimalistic by default
● Self contained web server
● Modular with extensions available
Some more on Flask...
Python Flask Architecture
Based on Werkzeug so mod_wsgi based
Built in web server
Uses Jinja2 for templating
Hosting avail...
Flask Extension Modules
Example modules (will cover later):
● Flask admin - generates an admin interface
● Flask login - l...
What can I use Flask for?
1. Projects with tight deadlines
2. Prototyping
3. In-house internal applications
4. Application...
App
Flask App - Log Viewer
A lightweight log viewer application, but without
the overhead of indexing. Provides:
● Access to s...
Flask 0.9 utilising:
● YAML (Yet Another Markup Language) for
configuration
● Jinja 2 templates for content separation
● T...
Python Modules
Used additional Python wrappers for
Grin - http://pypi.python.org/pypi/grin
● Provides search features (wra...
Main UI
Templating
<!doctype html>
{% include 'header.html' %}
{% include 'search.html' %}
{% macro genlink(func, filename) -%}
<a...
New route() for grep
@app.route("/grep/", methods=['GET', 'POST'])
def grep():
"""Search through a file looking for a matc...
Search Expression - using grin
def search_for_expression(output, filepaths, validfiles, expression, grepbefore, grepafter)...
Search UI
Modules
cache = Cache(app)
cache.init_app(app)
cache = Cache(config={'CACHE_TYPE': 'simple'})
#Use a decorator to cache a specific...
man = CouchDBManager()
man.setup(app)
# Create a local proxy to get around the g.couch namespace
couch = LocalProxy(lambda...
from flask_mail import Message
@app.route("/")
def index():
msg = Message("Hello",
sender="from@example.com",
recipients=[...
from flask import Flask, Response
from flask_principal import Principal, Permission, RoleNeed
app = Flask(__name__)
# load...
Q&A
Lightweight web frameworks
Upcoming SlideShare
Loading in …5
×

Lightweight web frameworks

19,708 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Lightweight web frameworks

  1. 1. Welcome... to the inaugural meeting of Chippenham Tech Chat...
  2. 2. Meetup Details Will be hosted once a month at Mango/Scisys - Methuen Park Presentations on various topics. If you're interested in doing one then propose it on the forum Meetup group http://www.meetup.com/Chippenham-Tech-Chat/ Google Groups Forum https://groups.google.com/forum/?fromgroups#! forum/chippenhamtechchat
  3. 3. Lightweight Web Frameworks Jonathan Holloway jholloway@mango-solutions.com twitter: jph98
  4. 4. Overview ● A brief history of web applications ● Past experience ● An overview of lightweight web frameworks ● An introduction to one web framework and it's features ● I won't go into
  5. 5. Web Frameworks - A Brief History ● CGI and Perl - circa 1993 ● PHP, Coldfusion - circa 1995 ● ASP - circa 1998 ● JSP and Servlet Spec - circa 1999 ● Struts - circa 2001 ● Rails - circa 2005 How many are there today?
  6. 6. 261 ! * at least
  7. 7. Used Java Servlets and JSP around 1999/2000. First introduction - somewhat painful. Then discovered Struts in 2001/2002 (pre 1.0 release). Vowed never to go back to JSP hell. In 2005/2006 we migrated our legacy Struts apps to Struts 2. Better still. SpringMVC came in around the same time. Past Experience - Cathedrals
  8. 8. Broken down into language (approx) 91 33 31 40 14 22 23 7
  9. 9. Past Experience - Post Java Then looked at PHP for doing more lightweight work. Used CakePHP 1.x then looked at CodeIgniter. Used Dojo (pre 1.0 release) and Velocity to build a rich client Javascript application.
  10. 10. Past Experience - First One Pager Then ended up building a rich client interface in Google Web Toolkit 1.x Then around 2007 went along to the Vancouver Ruby/Rails meetup. Talked about Rails/Merb then someone mentioned Sinatra. Then picked up Flask, looked at Ratpack in Geecon this year
  11. 11. Flask - Python
  12. 12. Really?
  13. 13. Here's what we would have have done back in the day with Apache Struts...
  14. 14. 1. Setup web.xml 2. Created an index.jsp to forward on to my app 3. Setup struts-config.xml and added a form and action mapping detailing my Action class 4. Create an Action & Action Form class
  15. 15. 5. Setup my forward on success 6. Put all this in a predefined folder structure 7. Package it all up into a war file 8. Deploy to Tomcat and Start
  16. 16. then.... 9. Fix the stupid errors 10. Deploy again and see Hello World in my browser. Maybe.
  17. 17. easy...
  18. 18. Others?
  19. 19. There's others !! There's a bunch of other lightweight web frameworks in various languages: ● Flask - Python ● Nancy - .NET ● Ratpack - Groovy/Java ● Berliner - CoffeeScript ● Dancer - Perl Classification of these...
  20. 20. Web Framework Taxonomy Sinatra, Flask, Berliner, Dancer, Ratpack, Nancy [Micro Frameworks] Rails, Django [Lightweight Frameworks] Play, Struts 2, Spring MVC [MOR] Google Web Toolkit, JSF [Component Based] Light Heavy
  21. 21. Sinatra - Ruby #!/usr/bin/env ruby require 'rubygems' require 'sinatra' get '/' do '<b>Hello, world!</b>' end
  22. 22. Nancy - dot NET public class SampleModule : Nancy. NancyModule { public SampleModule() { Get["/"] = _ => "Hello World!"; } }
  23. 23. Ratpack - Groovy get("/helloworld") { "Hello, World!" }
  24. 24. Berliner - Coffeescript app = require 'berliner' app.get '/', -> 'Hello, world!' app.run 4567
  25. 25. Properties of such frameworks? ● Minimalistic by default ● Self contained web server ● Modular with extensions available
  26. 26. Some more on Flask...
  27. 27. Python Flask Architecture Based on Werkzeug so mod_wsgi based Built in web server Uses Jinja2 for templating Hosting available on heroku, webfaction Celery integration for async task/job queuing
  28. 28. Flask Extension Modules Example modules (will cover later): ● Flask admin - generates an admin interface ● Flask login - login mechanism ● Flask cache - simple caching ● Flask couchdb - couchdb module ● Flask lesscss - less CSS template ● Flask lettuce - BDD ● Flask celery - distributed task queue Extensions registry here: http://flask.pocoo.org/extensions/
  29. 29. What can I use Flask for? 1. Projects with tight deadlines 2. Prototyping 3. In-house internal applications 4. Applications where system resources are limited, e.g. VM's hosted on Linode.com
  30. 30. App
  31. 31. Flask App - Log Viewer A lightweight log viewer application, but without the overhead of indexing. Provides: ● Access to specific application logs for users instead of them ssh'ing to the server to "less" them. ● Retrieve the head or tail a log file ● Search in logs (with grep) for an expression
  32. 32. Flask 0.9 utilising: ● YAML (Yet Another Markup Language) for configuration ● Jinja 2 templates for content separation ● The LESS dynamic stylesheet module Virtualenv - for creating an isolated Python environment to manage dependencies Python 2.6.1 (CPython) System Components
  33. 33. Python Modules Used additional Python wrappers for Grin - http://pypi.python.org/pypi/grin ● Provides search features (wraps GNU grep) ● Supports regex, before/after context ● File/dir exclusion Tailer - http://pypi.python.org/pypi/tailer/0.2.1 ● Display n lines of the head/tail of a file ● Allows "follow" of a file
  34. 34. Main UI
  35. 35. Templating <!doctype html> {% include 'header.html' %} {% include 'search.html' %} {% macro genlink(func, filename) -%} <a href="{{func}}/{{ filename }}/{{ session['grepnumlines'] }}">{{func}}</a> {%- endmacro %} {% for filename in session['validfiles']|sort %} <div class="logfile"> {{ session['validfiles'].get(filename)[0] }} - {{ genlink('head', filename) }} &nbsp;<span style="color:#cecece">|</span> &nbsp; {{ genlink('tail', filename) }} - {{ session['validfiles'].get(filename)[1] }} bytes </div> {% endfor %} {% include 'footer.html' %}
  36. 36. New route() for grep @app.route("/grep/", methods=['GET', 'POST']) def grep(): """Search through a file looking for a matching phrase""" # Validate the form inputs if request is None or request.form is None: return render_template('list.html',error='no search expression specified') if request.form['expression'] is None or len(request.form['expression']) == 0: return render_template('list.html',error='no search expression specified') expression = request.form['expression'].strip() output = "" filepaths = [] output += search_expr(output, filepaths, session.get('validfiles'), expression, request.form['grepbefore'], request.form ['grepafter']) if not output: return render_template('list.html', error='No results found for search expression') expression = expression.decode('utf-8') highlight = '<span class="highlightmatch">' + expression + '</span>' highlightedoutput = output.decode('utf-8').replace(expression, highlight) return render_template('results.html', output=highlightedoutput,filepaths=filepaths,expression=expression)
  37. 37. Search Expression - using grin def search_for_expression(output, filepaths, validfiles, expression, grepbefore, grepafter): """Carry out search for expression (using grep context) on validfiles returning matching files as output""" options = grin.Options() options['before_context'] = int(grepbefore) options['after_context'] = int(grepafter) options['use_color'] = False options['show_filename'] = False options['show_match'] = True options['show_emacs'] = False options['show_line_numbers'] = True searchregexp = re.compile(expression) grindef = grin.GrepText(searchregexp, options) for file in validfiles: filepath = validfiles.get(file)[0] report = grindef.grep_a_file(filepath) if report: output += '<a name="filename' + str(anchorcount) + '"></a><h2>' + filepath + '</h2>' filepaths.append(filepath) reporttext = report.split("n") for text in reporttext: if text: output += "line " + text + "<br>" return output
  38. 38. Search UI
  39. 39. Modules
  40. 40. cache = Cache(app) cache.init_app(app) cache = Cache(config={'CACHE_TYPE': 'simple'}) #Use a decorator to cache a specific template with @cache.cached(timeout=50) def index(): return render_template('index.html') Flask Cache
  41. 41. man = CouchDBManager() man.setup(app) # Create a local proxy to get around the g.couch namespace couch = LocalProxy(lambda: g.couch) # Store a document and retrieve document = dict(title="Hello", content="Hello, world!") couch[some_id] = document document = couch.get(some_id) Flask CouchDB
  42. 42. from flask_mail import Message @app.route("/") def index(): msg = Message("Hello", sender="from@example.com", recipients=["to@example.com"]) Flask Mail
  43. 43. from flask import Flask, Response from flask_principal import Principal, Permission, RoleNeed app = Flask(__name__) # load the extension principals = Principal(app) # Create a permission with a single Need, in this case a RoleNeed. admin_permission = Permission(RoleNeed('admin')) # protect a view with a principal for that need @app.route('/admin') @admin_permission.require() def do_admin_index(): return Response('Only if you are an admin') Flask Principles
  44. 44. Q&A

×