Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to not Make a CRUD'y Web App

How to not Make a CRUD'y Web App

Views, models, and ORMs are great to quickly stand up a CRUD application. What if you want something leaner & faster to do non-CRUD things? Django is not ideal for non-CRUD applications, but Pyramid, Flask, and other microframeworks excel at this. This talk will show how to quickly build a non-CRUD scraping and JSON consuming application with Pyramid and the benefits of using a microframework.

Calvin Hendryx-Parker

February 08, 2015
Tweet

More Decks by Calvin Hendryx-Parker

Other Decks in Programming

Transcript

  1. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  4. 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

    View full-size slide

  5. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. 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

    View full-size slide

  9. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  20. 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

    View full-size slide

  21. 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

    View full-size slide

  22. 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

    View full-size slide

  23. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. @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

    View full-size slide

  27. 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

    View full-size slide

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

    View full-size slide

  29. 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

    View full-size slide

  30. 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

    View full-size slide

  31. 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

    View full-size slide

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

    View full-size slide