Your SlideShare is downloading. ×
Lightweight web frameworks
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Lightweight web frameworks

18,980
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
18,980
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Welcome... to the inaugural meeting of Chippenham Tech Chat...
  • 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. Lightweight Web Frameworks Jonathan Holloway jholloway@mango-solutions.com twitter: jph98
  • 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. 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. 261 ! * at least
  • 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. Broken down into language (approx) 91 33 31 40 14 22 23 7
  • 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. 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. Flask - Python
  • 12. Really?
  • 13. Here's what we would have have done back in the day with Apache Struts...
  • 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. 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. then.... 9. Fix the stupid errors 10. Deploy again and see Hello World in my browser. Maybe.
  • 17. easy...
  • 18. Others?
  • 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. 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. Sinatra - Ruby #!/usr/bin/env ruby require 'rubygems' require 'sinatra' get '/' do '<b>Hello, world!</b>' end
  • 22. Nancy - dot NET public class SampleModule : Nancy. NancyModule { public SampleModule() { Get["/"] = _ => "Hello World!"; } }
  • 23. Ratpack - Groovy get("/helloworld") { "Hello, World!" }
  • 24. Berliner - Coffeescript app = require 'berliner' app.get '/', -> 'Hello, world!' app.run 4567
  • 25. Properties of such frameworks? ● Minimalistic by default ● Self contained web server ● Modular with extensions available
  • 26. Some more on Flask...
  • 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. 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. 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. App
  • 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. 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. 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. Main UI
  • 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">&#124;</span> &nbsp; {{ genlink('tail', filename) }} - {{ session['validfiles'].get(filename)[1] }} bytes </div> {% endfor %} {% include 'footer.html' %}
  • 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. 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. Search UI
  • 39. Modules
  • 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. 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. from flask_mail import Message @app.route("/") def index(): msg = Message("Hello", sender="from@example.com", recipients=["to@example.com"]) Flask Mail
  • 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. Q&A

×