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

Joyful Python Web App development with Appier

Joyful Python Web App development with Appier

João Magalhães, VP of Engineering at Platforme and the author of the web framework Appier shares his insights on joyful development for the web

Python Porto

March 24, 2017
Tweet

More Decks by Python Porto

Other Decks in Programming

Transcript

  1. A bit of history • Born out of Hive Solutions’

    necessity • Built in 2013 out of Flask Quorum set of Flask extensions • Simple design influenced by Flask • “Some batteries included” philosophy
  2. “Some batteries included” • Django, batteries included (too bloated) •

    Flask (minimalist, some major things are missing) • Appier in between both
  3. Design decisions • Object oriented in nature • Data model

    layer out of the box • Built for easy REST API building • Extensible by design • Scalable and performant • Asynchronous (coroutines and futures)
  4. Async support design • Scalable (solves the C10K problem) •

    Compatible (supports both Python 2.6+ and 3.3+) • Simple (code looks as similar as possible to “normal” blocking Appier code) • Uses (semi-)coroutines together with futures • Works great with the asyncio module (from standard lib)
  5. What’s asynchronous on Appier • Async from top to bottom

    & out-of-the box • Lots of challenges implementing it • Template rendering • Data layer • Filesystem IO, HTTP clients, etc.
  6. Async example class AsyncHTTPApp(appier.App): @appier.route("/", "GET") async def example(self): return

    await appier.get_w("https://appier.hive.pt/") AsyncHTTPApp().serve()
  7. Another async example class AsyncHTTPApp(appier.App): @appier.route("/", "GET") async def example(self):

    url = "https://appier.hive.pt/” await asyncio.sleep(3) response = await aiohttp.request("GET", url) return await response.read() AsyncHTTPApp().serve()
  8. Async data layer class AsyncModelsApp(appier.App): @appier.route("/", "GET") async def example(self):

    person = models.Person(name="Tobias") await person.save() print(person.id) person = await models.Person.get(name="Tobias") return person.map() HelloApp().serve()
  9. Templates • Modular template support • Jinja2 is first class

    citizen • Async rendering support for Jinja2 out-of-the-box
  10. Models • Simple model design approach • Multiple back-end support

    • Validations, pre_*, post_* and on_* hooks • Custom type support (implement loads() and dumps()) • Async support (still under construction)
  11. Models - Example class Person(appier.Model): identifier = appier.field( type =

    int, index = True, increment = True ) name = appier.field() age = appier.field( type = int )
  12. Models - Custom Types class Person(appier.Model): thumbnail = appier.field( type

    = appier.image( width = 400, height = 400, format = "png" ) )
  13. Models - Custom Types class DateTime(appier.Type): def loads(self, value): self._datetime

    = datetime.datetime.utcfromtimestamp(value) def dumps(self): return self.timestamp() def timestamp(self): return time.mktime(self._datetime.timetuple())
  14. • Admin interface • Access control • Auto-snapshotting of models

    • Encrypted model fields • App configuration (JSON, env variables, DB, other) Other cool features
  15. • nicholaskirkwood.com • budy.hive.pt • rocklobby.com • oioba.com • webook.pt

    • dev.windows.com • karl.com • my-swear.com • hive.pt • lugardajoia.com Who uses it ?
  16. What’s joy ? • Having a minimal set of dependencies

    • Owning the code by understanding it • Having code that scales properly • Using simple tools to build complex things