Slide 1

Slide 1 text

How to not make a CRUD'y web app PyTennessee 2015 Feb 8th, 2015 How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 2

Slide 2 text

Who is this guy? How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 3

Slide 3 text

Right tools, Right Job CRUD vs non-CRUD How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 4

Slide 4 text

Django's Strengths Powerful Fast Big Community No depenedanices Built-in Tools ORM Templating Contrib How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 5

Slide 5 text

What if we don't need all of these extra bits? We aren't always writing CRUD apps How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 6

Slide 6 text

The Alternatives Microframeworks! Pyramid Flask Bottle How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 7

Slide 7 text

Hello World Comparison How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 8

Slide 8 text

Django import sys from django.conf import settings settings.configure( DEBUG = True, SECRET_KEY ='thisisthesecretkey', ROOT_URLCONF = __name__, MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ), ) from django.conf.urls import url from django.http import HttpResponse def index(request): return HttpResponse('Hello World') urlpatterns = ( url(r'^$', index), ) if __name__ == "__main__": from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 9

Slide 9 text

Pyramid from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.response import Response def hello_world(request): return Response('Hello %(name)s!' % request.matchdict) if __name__ == '__main__': config = Configurator() config.add_route('hello', '/hello/{name}') config.add_view(hello_world, route_name='hello') app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever() How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 10

Slide 10 text

Let's get the CRUD out How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 11

Slide 11 text

Quickly Scratch an Itch How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 12

Slide 12 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 13

Slide 13 text

How can we get at the data? How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 14

Slide 14 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 15

Slide 15 text

alpha% http --auth XXXXXXXXX:X https://api.myintervals.com/person\?firstname=calvin HTTP/1.1 200 OK Content-Encoding: gzip Content-Length: 343 Content-Type: application/json Date: Sat, 07 Feb 2015 19:19:04 GMT P3P: CP="OTI DSP COR CUR ADMo TAIo PSAo CONi OUR PUBi IND NAV ONL PUR PRE", policyref="/w3c/p3p.xml" Server: Apache Vary: Accept-Encoding nnCoection: close { "code": 200, "listcount": 1, "person": [ { "active": "t", "allprojects": "t", "client": "Six Feet Up", "clientid": "xxxxxx", "clientlocalid": "5", "firstname": "Calvin", "group": "Administrator", "groupid": "2", "id": "xxxxx", "lastlogin": "2015-02-07 11:03:50", "lastname": "Hendryx-Parker", "localid": "4", "notes": "", "numlogins": "709", "primaryaccount": "f", "private": "f", "restricttasks": "f", "timezone": "America/New_York", "timezone_offset": "Eastern Time (US & Canada)", "tips": "f", "title": "CTO", "username": "calvin" } ], "personid": 25233, How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 16

Slide 16 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 17

Slide 17 text

Magic may now happen Introducing Bill How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 18

Slide 18 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 19

Slide 19 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 20

Slide 20 text

Simplicity Cannot analyze code. No Pygments lexer found for "shell". .. code:: shell alpha% pcreate -l Available scaffolds: alchemy: Pyramid SQLAlchemy project using url dispatch starter: Pyramid starter project zodb: Pyramid ZODB project using traversal How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 21

Slide 21 text

Cannot analyze code. No Pygments lexer found for "shell". .. code:: shell alpha% pcreate -t starter demo_app Creating directory /Users/calvin/Documents/Projects/pytn/demo_app Recursing into +package+ Creating /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/ Copying __init__.py to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/__init__.py Recursing into __pycache__ Creating /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/__pycache__/ Recursing into static Creating /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/static/ Copying pyramid-16x16.png to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/static/pyramid-16x16.png Copying pyramid.png to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/static/pyramid.png Copying theme.css to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/static/theme.css Copying theme.min.css to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/static/theme.min.css Recursing into templates Creating /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/templates/ Copying mytemplate.pt_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/templates/mytemplate.pt Copying tests.py_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/tests.py Copying views.py_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/demo_app/views.py Copying CHANGES.txt_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/CHANGES.txt Copying MANIFEST.in_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/MANIFEST.in Copying README.txt_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/README.txt Copying development.ini_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/development.ini Copying production.ini_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/production.ini Copying setup.py_tmpl to /Users/calvin/Documents/Projects/pytn/demo_app/setup.py =============================================================================== Tutorials: http://docs.pylonsproject.org/projects/pyramid_tutorials Documentation: http://docs.pylonsproject.org/projects/pyramid Twitter (tips & updates): http://twitter.com/pylons Mailing List: http://groups.google.com/group/pylons-discuss Welcome to Pyramid. Sorry for the convenience. =============================================================================== How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 22

Slide 22 text

Minimalism def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ set_cache_regions_from_settings(settings) config = Configurator(root_factory=root_factory, settings=settings) config.add_route('userdash', 'dash/{userid}') config.add_route('userdash_ymd', 'dash/{userid}/{year}/{month}/{day}') config.add_view(view='billable.views.user_dash_view', route_name='userdash') config.add_view(view='billable.views.user_dash_view', route_name='userdash_ymd') config.add_static_view('static', 'static', cache_max_age=3600) config.add_static_view( 'deform_static', 'deform:static', cache_max_age=3600) config.add_static_view('static-deform_bootstrap', 'deform_bootstrap:static') config.scan() return config.make_wsgi_app() How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 23

Slide 23 text

Show us traversal! from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.response import Response class Resource(dict): pass def get_root(request): return Resource({'a': Resource({'b': Resource({'c': Resource()})})}) def hello_world_of_resources(context, request): output = "Here's a resource and its children: %s" % context return Response(output) if __name__ == '__main__': config = Configurator(root_factory=get_root) config.add_view(hello_world_of_resources, context=Resource) app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever() How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 24

Slide 24 text

How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 25

Slide 25 text

Back to our Bill app How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 26

Slide 26 text

@view_config(route_name='userdash', context=FrontPage, renderer='templates/userdash.pt') @view_config(route_name='userdash_ymd', context=FrontPage, renderer='templates/userdash.pt') def user_dash_view(request): """View to show the users hours dashboard """ ... # (some implementation here) return { 'setup': True, 'hours': hours, 'goal_reached': goal, 'goal': billable_goal, 'billable_table': billable_table, 'firstname': firstname, 'userid': current_user, 'css_color': css_color, 'retrieved': retrieved, 'selected_weekday': selected_week.monday(), 'next_week': next_week, 'prev_week': prev_week, } How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 27

Slide 27 text

Flexbility Template Language Pyramid Bindings Default Extensions Chameleon pyramid_chameleon .pt, .txt Jinja2 pyramid_jinja2 .jinja2 Mako pyramid_mako .mak, .mako How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 28

Slide 28 text

Flexbility Database Choices How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 29

Slide 29 text

Speed from beaker.cache import cache_region @cache_region('one_year', 'load_username') def _username_from_personid(personid, api_key): auth = (api_key, 'X') headers = {'Accept': 'application/json'} timetask_person = '%s/person/%s/' % (TIMETASK_API_BASE, personid) person_json = requests.get( timetask_person, auth=auth, headers=headers, ) person_json.raise_for_status() person = json.loads(person_json.content) return person['person']['username'] How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 30

Slide 30 text

Reliability Where Pyramid source code is concerned, our motto is: "If it ain’t tested, it’s broke". How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 31

Slide 31 text

Not all your apps need to be CRUD'y And you probably don't need a hammer factory factory How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015

Slide 32

Slide 32 text

Thanks! How to not make a CRUD'y web app - Calvin Hendryx-Parker - PyTennessee 2015