Keynote: Sketching out a Django redesign
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 32 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/45448 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
DjangoCon Europe 20193 / 32
5
8
14
22
24
27
29
30
31
00:00
Right angleMultiplication signFlow separationProjective planeOpen sourceStreaming mediaPosition operatorProcess (computing)Computer programmingDifferent (Kate Ryan album)Moment (mathematics)Software maintenanceSoftware frameworkAuthorizationDirected graph
01:10
Concurrency (computer science)Endliche ModelltheorieCommunications protocolServer (computing)Directed graphWordNormal (geometry)Real-time operating systemWeb applicationPoint (geometry)Thread (computing)Functional (mathematics)Form (programming)Web-DesignerThomas BayesWater vaporGateway (telecommunications)Proxy serverWeb serviceWebsiteNumberDependent and independent variablesBuildingSoftwareOnline chatDomain nameWeb 2.0
02:39
Task (computing)NumberMultiplicationProcess (computing)SynchronizationConcurrency (computer science)Concurrency (computer science)Process (computing)Endliche ModelltheorieTask (computing)Dependent and independent variablesPoint (geometry)Multiplication signCore dumpExterior algebraControl flowBefehlsprozessorLevel (video gaming)NumberDatabaseSingle-precision floating-point formatServer (computing)Thread (computing)BitMappingWeb-DesignerConnected spaceGame controllerFlow separationMiniDiscDifferent (Kate Ryan album)Code2 (number)Operating systemWeb servicePhysical systemComputer programmingIndependence (probability theory)Block (periodic table)Directed graphMultiplicationWeightSystem callVirtual machineScalabilityCausalityComputer animation
06:11
Task (computing)NumberMultiplicationProcess (computing)SynchronizationConcurrency (computer science)Run time (program lifecycle phase)Different (Kate Ryan album)Control flowPoint (geometry)Thread (computing)Operator (mathematics)Programmer (hardware)MiniDiscEndliche ModelltheorieDatabaseSoftwareGame controllerRun time (program lifecycle phase)Context awarenessState of matterOperating systemWordDirected graphMultiplication signComputer programmingComputer animation
07:29
Computer networkDatabaseFunction (mathematics)SynchronizationMiniDiscInstance (computer science)SoftwareFunctional (mathematics)Level (video gaming)Directed graphContext awarenessBitCodePosition operatorOrder (biology)Term (mathematics)
08:41
Device driverWritingLibrary (computing)DatabaseLevel (video gaming)Directed graphPiSoftware developerDifferent (Kate Ryan album)Type theoryFunctional (mathematics)Core dumpProgramming paradigmBitSystem callRegular graphComputerComputer programming
09:38
ComputerWeb serviceWeb pageWeb 2.0Volume (thermodynamics)Server (computing)Flow separationInstance (computer science)
10:18
System programmingParallel computingFlow separationServer (computing)SoftwareRoundness (object)Product (business)Software developerQuicksortReal-time operating systemAxiom of choiceDifferent (Kate Ryan album)Block (periodic table)Web servicePhysical systemScalabilityContext awarenessRight angleOcean currentWebsiteTelecommunicationThread (computing)WordArithmetic meanCASE <Informatik>Multiplication signDirected graphOpen setConnected spaceCodeConcurrency (computer science)Parallel portBuildingWeb 2.0
13:06
Java appletScripting languageVertex (graph theory)Benchmark1 (number)Server (computing)BitSoftware testingLibrary (computing)Different (Kate Ryan album)Block (periodic table)Web 2.0CASE <Informatik>GodBit rateMultiplication signBenchmarkDatabaseSoftware frameworkWeb applicationArtistic renderingResultantNumberFlow separationMultitier architectureNetwork topologyGreatest elementStandard deviationFilm editing
14:58
Dependent and independent variablesMobile appInterface (computing)Thread (computing)Web 2.0Software frameworkVibrationConstraint (mathematics)Interface (computing)Concurrency (computer science)DemosceneDirected graphServer (computing)Cartesian coordinate systemContext awarenessSocket-Schnittstelle
15:59
Interface (computing)SynchronizationDependent and independent variablesExterior algebraNatural numberSoftware development kitGodInterface (computing)Cartesian coordinate systemDirected graphWebsiteConnected spaceNetwork socketSocket-SchnittstelleWeb 2.0Order (biology)UML
16:59
Mobile appEmailMessage passingComputer virusFunctional (mathematics)InformationConnected spaceVariable (mathematics)Key (cryptography)Interface (computing)State of matterCASE <Informatik>Bit rateWeb applicationServer (computing)Dependent and independent variablesWeb 2.0Streaming media
18:07
Interface (computing)Task (computing)Server (computing)Event horizonEvent horizonWeb 2.0Peer-to-peerServer (computing)Direction (geometry)Spherical capContext awarenessMultiplication signClient (computing)Real-time operating systemRootHTTP cookieWeb pageQueue (abstract data type)Adaptive behaviorHome pageRight angleCommunications protocolChemical equationRoundness (object)WebsiteSoftware development kitInterface (computing)ArmVector potentialCharacteristic polynomialTelecommunicationDifferent (Kate Ryan album)Domain nameTask (computing)Term (mathematics)RoutingConnected spaceComputer-assisted translation
20:32
HypercubeMaizeServer (computing)Software frameworkLambda calculusDirected graphServer (computing)Moment (mathematics)Flow separationDifferent (Kate Ryan album)ImplementationElectronic mailing listSoftware frameworkWeb 2.0
21:17
Server (computing)InformationMotion blurCartesian coordinate systemRouter (computing)Process (computing)Stack (abstract data type)Slide ruleSoftware frameworkBuildingDirected graphBitWeb 2.0Standard deviationASCIIRight angleInterface (computing)Dependent and independent variablesMereologyValidity (statistics)Instance (computer science)Physical systemView (database)
22:44
Dependent and independent variablesMobile appComputer virusClient (computing)Software testingInterface (computing)Client (computing)BitLevel (video gaming)Proper mapState of matterInterface (computing)Key (cryptography)Software testingDependent and independent variablesConnectivity (graph theory)Raw image formatSoftware frameworkStandard deviation1 (number)SoftwareSocial classLibrary (computing)Web 2.0Aliasing
24:25
Configuration spaceMiddlewareSoftware testingMiddlewareInstance (computer science)Web 2.0Client (computing)Interface (computing)Network socketDependent and independent variablesGoodness of fitSoftware frameworkEmailImplementationType theorySign (mathematics)WebsiteKey (cryptography)Different (Kate Ryan album)Disk read-and-write headSoftware developerLevel (video gaming)Multiplication sign
26:06
Dependent and independent variablesMiddlewareDependent and independent variablesLevel (video gaming)MiddlewareServer (computing)Process (computing)Interface (computing)Message passingSocial classInstance (computer science)BuildingNumbering schemeComputer animation
27:05
Fluid staticsComputer fileMobile appConnectivity (graph theory)View (database)Web 2.0Web applicationMobile appFirewall (computing)Coma BerenicesPoint (geometry)Software frameworkComputer fileBuildingInterface (computing)Server (computing)Datei-ServerASCIIFluid staticsUML
27:56
Mobile appSocial classView (database)Dependent and independent variablesQuantum entanglementSoftware frameworkConfiguration spaceEuclidean vectorBuildingSoftware frameworkSet (mathematics)Interface (computing)Similarity (geometry)View (database)QuicksortBounded variationLevel (video gaming)BitConfiguration spacePoint (geometry)Different (Kate Ryan album)Connectivity (graph theory)Single-precision floating-point formatCartesian coordinate systemGroup actionDistanceSound effectInstance (computer science)MultilaterationNP-hardWeb 2.0Software developerSoftware testingComplex (psychology)Percolation theoryComputer animation
29:28
Kolmogorov complexityComponent-based software engineeringInterface (computing)Software frameworkMobile appClient (computing)Stack (abstract data type)DatabaseStandard deviationThread (computing)Concurrency (computer science)Computer configurationSynchronizationComplex (psychology)Software testingSingle-precision floating-point formatConsistencyDifferent (Kate Ryan album)Connectivity (graph theory)AbstractionClient (computing)Interface (computing)Task (computing)Right angleDatabaseDevice driverThread (computing)Level (video gaming)CodeSynchronizationSpacetimeDirected graphGradientGrass (card game)State of matterComputer animation
31:20
Programmable read-only memoryDatabaseQuery languageDean numberWindowCore dumpBit rateBoolean algebraIntegerRaw image formatDatabaseDevice driverQuery languageInterface (computing)Core dumpSoftware developerDirected graphTable (information)Level (video gaming)Human migrationDatabase transactionSource codeComputer animationXMLUML
32:23
DatabaseDatabase transactionRollback (data management)Endliche ModelltheorieObject-relational mappingObject (grammar)DatabaseQuicksortDatabase transactionConnected spaceLine (geometry)Level (video gaming)Independence (probability theory)Human migrationConnectivity (graph theory)UML
33:16
Object (grammar)Digital filterData modelQuery languageDifferent (Kate Ryan album)ExpressionBuildingDirected graphKey (cryptography)Instance (computer science)Entire functionQuery languageSet (mathematics)Similarity (geometry)ResultantError messageWeb pageEndliche ModelltheorieBitRight angleSystem callComputer animation
34:57
DatabaseQuery languageInstance (computer science)DatabaseEndliche ModelltheorieWritingField (computer science)Electric generatorCodeSinc functionQuery languageInstance (computer science)Client (computing)System administratorGame controllerNumberBitExpert systemType theoryCASE <Informatik>View (database)String (computer science)Template (C++)Computer animation
36:55
DatabaseDatabase transactionDependent and independent variablesDatabase transactionPeer-to-peerOperator (mathematics)Library (computing)SpacetimeOrder (biology)Server (computing)Connected spaceElectric generatorWritingComputer fileDatabaseGateway (telecommunications)Process (computing)Physical systemDirected graphCuboidConcurrency (computer science)
38:26
Cache (computing)PasswordLibrary (computing)Validity (statistics)Task (computing)PasswordHash functionSingle-precision floating-point formatOperator (mathematics)Level (video gaming)Thread (computing)SoftwareBlock (periodic table)DatabaseForm (programming)Loop (music)Different (Kate Ryan album)BuildingDirected graphNormal (geometry)
40:15
SynchronizationDatabaseServer (computing)Software frameworkData typeLibrary (computing)Software testingUniform resource locatorHill differential equationKey (cryptography)Directed graphSoftware frameworkWeb 2.0Set (mathematics)Slide ruleBitConfiguration spaceConnectivity (graph theory)Different (Kate Ryan album)Point (geometry)DivisorComputer animationSource code
41:26
MathematicsVoltmeterError messageTemplate (C++)Computer wormInclusion mapEndliche ModelltheorieSimilarity (geometry)Point (geometry)BitDifferent (Kate Ryan album)Validity (statistics)Directed graphType theoryPhysical systemSerial portSoftware frameworkLibrary (computing)Artistic renderingForm (programming)View (database)DatabaseSoftwareSource code
42:30
Lie groupStack (abstract data type)Server (computing)Task (computing)Pairwise comparisonInstance (computer science)Single-precision floating-point formatConnectivity (graph theory)Configuration spaceMiddlewareRoutingServer (computing)Exception handlingMobile appDefault (computer science)Error messageArrow of timeSocket-SchnittstelleTerm (mathematics)10 (number)BuildingMultiplication sign2 (number)Real-time operating systemWeb 2.0Event horizonMoment (mathematics)Task (computing)Gateway (telecommunications)Pay televisionProxy serverClient (computing)Point (geometry)Source codeComputer animation
44:14
EmailDependent and independent variablesMobile appHome pageSynchronizationStack (abstract data type)Raw image formatInterface (computing)Connectivity (graph theory)QuicksortSoftware frameworkWeb 2.0DatabaseThread (computing)Power (physics)Standard deviationArithmetic meanStack (abstract data type)Surjective functionPoint (geometry)BitMultiplication signPhysical lawVideo gameDirected graphGodKey (cryptography)Military baseView (database)Computer animationSource code
46:50
Message passingLevel (video gaming)Message passingFunctional (mathematics)Communications protocolProduct (business)Time zoneStructural loadReal-time operating systemMereologyDirected graph
47:54
CollaborationismLiquidSource codeSoftware frameworkMultiplication signVector potentialQuicksortPoint (geometry)Event horizonTerm (mathematics)Order (biology)Open setLocal ringComputer animation
49:04
ProduktraumProduct (business)Game controllerDirection (geometry)Software developerOrder (biology)Strategy gameSoftware frameworkPower (physics)1 (number)Capability Maturity ModelWhiteboardSlide ruleRow (database)Constraint (mathematics)Rule of inferenceNumberPoint (geometry)Game theorySet (mathematics)Level (video gaming)Multiplication signOpen sourceMereologyComputer animation
52:50
Slide ruleComputer animation
Transcript: English(auto-generated)
00:01
We're there. Okay. Yeah, one last thing before I get started. I think my kids might be watching on the live stream at home. Hi, boys! Hi, kids! Thank you! Okay. Great. Hi. Thank you very much. My name is Tom Chrissey. I've been a long-time Python and Django
00:23
user. I'm the maintainer of several open source projects, and I'm most well known for being the author of Django Rest Framework. Now, I'm fortunate enough to be in a position where I work on open source full-time now for my day job.
00:41
Django Rest Framework launched a sponsorship program where lots and lots of different companies can contribute a small amount per month, and this is what pays for my day job at the moment. I've been spending as well as working on Django Rest Framework
01:04
and helping manage that, spending a lot of time recently on async which is what I'm going to talk about today. So, Python is at a really big crossroads right now. Python 3.5 introduced a new functionality in the form of the async and await keywords. The
01:28
async and await keywords help us use an entirely new concurrency model that is much, much more efficient than the existing thread concurrency model. This is going to let
01:42
us do some really exciting things. For one thing, it lets us build very, very high throughput web services. It allows us to make non-blocking HTTP requests so we can build Python gateway APIs or proxy services that are able to handle very high concurrency,
02:08
high throughput, which is a domain where Python has traditionally not excelled in. And it will also allow us to handle real-time network protocols, such as WebSockets, so
02:24
we will be able to start building more and more real-time responsive web applications, chat services, games, real-time monitoring, all of these kinds of things. Before we dive into this, a little bit of ground work. Concurrency. What is concurrency?
02:49
Concurrency is all about the number of tasks that your server is able to handle simultaneously. In the web development land, this maps on to how many HTTP connections is your server
03:04
able to hold open at the same time? And then, in turn, also influences what is the throughput that your server is able to achieve? How many requests per second can each individual server handle? So what are some of the ways that we have
03:23
to increase the concurrency of these web services that we're building? So the bluntest hammer in our toolbox, our sledgehammer, is multi-host, so horizontal scaling, where you add more servers running the same code base, and you're going to be able to handle
03:43
a greater number of requests per second. Well, let's bring that down a level to a single server. How can we increase the concurrency on a single server? Within a single server, we'll have a number of CPU cores. We want to make sure that all of those CPU cores
04:01
are fully utilized all the time, as much as possible, so we can run multiple processes within each machine, all pretty much completely independent, but all running at the same time. Okay, bring that down. Again, another level, how do we increase the concurrency
04:23
within a single process running on a single server? So traditionally, what we've used is threaded concurrency, and with threaded concurrency, what happens is we have a number of simultaneous flows of control running through our program, and each individual flow
04:43
of control will have large chunks of time where it's not utilizing the CPU, because it's waiting on IO from the rest of the system. So any time your program goes off and makes an HTTP request, makes a database access, accesses some disk IO, there's this
05:10
relatively huge chunk of time when that thread of control is not able to do anything else until it gets a response back from the operating system. So with multi-threading,
05:21
what the operating system does for you is handles interleaving several different flows of control and switches between them very, very quickly, so it appears as if all these flows of control are happening at the same time. Now, more recently, the async model
05:41
has been introduced, and the key point to take away at this point in time is async is an alternative to multi-threading, right? With async, you will have multiple tasks rather than multiple threads, and your multiple tasks will all be running within a single thread, but you will still have multiple processes, all running lots and lots of
06:05
little tasks within it, and you will still be running across multiple different hosts, and async is, as we said, far more efficient. So what are the differences between these two? With threaded concurrency, everything's managed by the operating system, and you
06:27
don't get to see as a programmer when am I going to switch between one of my two different threads of control. In async, it's a completely different model in that it's
06:40
managed by the runtime. It's managed by Python itself or by Node or whatever runtime you happen to be using, and the points of context switching between these different flows of control are still the points at which you're performing IO, so network
07:01
requests, database accesses, disk accesses, but they have to be explicitly marked in the program so that the runtime knows, okay, here's a point at which I can context switch. So you have this entirely new syntax that is introduced, the async and await keywords,
07:25
and what's problematic is that these two models are largely incompatible. If you're going to have explicit context switching, then you need to have explicit context switching
07:41
all the way through. So if you're low level, I'm making a network request as being explicitly marked, then anything that calls into that also needs to be marked up as being an async function. And although there are ways that we can mediate between these two styles,
08:03
it's a bit fiddly. So there's this huge challenge for the ecosystem. It's a little bit of a fork in the road. And it's important to acknowledge that, as with any new technology,
08:20
there are costs as well, and we need to talk about them up front and recognise them so that we're in a good position to judge what the trade-offs are. So there's this huge up-front cost in terms of all of the new code that needs to be written in order to work with async. So for one thing, all of the low-level networking
08:46
stuff, all of the database drivers or making HTTP requests, or exactly how do you go about making disk.io, people need to write low-level async libraries to interact with that, because
09:01
it doesn't exist in the standard library, because it wasn't a thing when Python was not 3.5. Not quite true, but pretty much. What else? Okay. Well, it's a different paradigm, and there's a little bit more to think about as well as a developer. There's two different
09:24
types of function call you've got now. You've got async function calls, which is anything that is making IO, and you've got regular function calls, which is only allowed to just be doing regular programming-type stuff. It's using the CPU, and it's performing some kind of computation. One of the other reasons that it's worthwhile being cautious
09:49
here as well is you might not care about throughput. So, when you're looking at the performance of your web service, the thing that your users will most care about is how
10:03
long does it take, once they've made a request, for them to get a page back in front of them? What is the latency of the request? Async has an influence on that, but it's more complicated. Unless you are building a very high-volume service, the throughput
10:25
that it's able to handle might not matter that much. Unless you have several server instances, why do you care that it could handle high-load? Fine, so that's the things
10:41
to bear in mind, but the benefits, right? Sometimes the performance really does matter. In the cases where it does, it's really, really important that this should not be
11:00
a blocker for businesses adopting Python. We want to be able to build hugely scalable web services with Python, and we want the mega companies who are developing these flagship services to be choosing Python right at the start, building highly successful products with it, and being able to go to the rest of the world, hey, look at this
11:23
awesome thing that company XYZ has built in Python, and for them to go, yes, this was a great development experience for our team, and we're very happy with the choice that we made. What else? Real-time. Async, because Async is much more resource-efficient,
11:44
we're able to hold open lots and lots of network connections without that having a high impact, so we can hold open things like WebSockets, and we could do real-time communications, non-blocking HTTP requests, being able to perform parallelization within
12:05
our codes without that being a heavy-weight thing that branching lots of new threads would be. The explicit IO is actually also a benefit as well, but we'll come to that later in the talk, and one other thing to say here is performance can mean different
12:25
things in different contexts, right? So being able to build very highly concurrent web services, well, a flip-way round of looking at it, that is, on very lightly resourced systems, on embedded systems, these sorts of things will work really, really well. Or suppose
12:49
you don't require high throughput on your site most of the time, but it's only when you get a huge traffic spike, your service is much, much more resilient to that, okay? So it doesn't have to always be about this is just about high-throughput services
13:04
all the time. There are other reasons why it's important. And there's this other thing, you know. It is something that has been said lots of times. People say, Python's slow. We don't want to use Python for XYZ because Python's slow. Now, yeah, okay,
13:26
so, the next one is the test case. The tech empower benchmarks are the least awful ones that are around. They've got a number of different test cases that exercise various different bits of do some database stuff, do reads, writes, whatever. This particular
13:44
test case I think is the most representative of web applications because it does a little bit of database reading, it does a little bit of template rendering, and it does a bit of exercising the web stack. And, yes, I've cut some Go results off of the top here,
14:03
and, yes, I've cut lots and lots of results from several different frameworks off the bottom here, but the important things to look at are this one at the top. This is Go written against the Go standard library. The ones in yellow, those are all node-based,
14:23
and these ones in blue are both Python. And we've got a single very beefy server there that on its own is servicing 70,000 requests per second, which is probably more than you need. So, it's about making sure that there isn't this block at a business
14:46
adoption. Python is in the same ballpark as Node and Go for almost all intents and purposes that we in this room would probably need. So, okay, great. We would
15:03
like to start taking advantage of this. What do we need to do? The first thing in the stack that we run into is Wysgi. Wysgi is the interface that exists between the server, Gunicorn, or uWysgi, or something like that, and the application
15:27
framework, the web framework. And Wysgi has a couple of very big constraints for what we'd like to be able to do, one of which is inherently a thread concurrency
15:41
interface. It doesn't have that async definition on there, so it's not allowed to do any async context switching inside it. And it's designed purely for handling HTTP requests and responses, so it's got no easy way to adapt it for web sockets. So, hello, Asgi. Along comes Django channels, which originally
16:09
was designed in order to deal with web sockets in Django by largely keeping separate the asynchronous nature of handling the web socket connections from the synchronous nature of the thread-based Django codebase. And it
16:26
has gradually evolved under Andrew Godwin's wonderful guidance, wherever, there we go, into becoming a general-purpose application interface, an alternative to Wysgi, an async alternative to Wysgi, an async alternative to
16:44
Wysgi that also handles web sockets, that is also able to deal with, and that is also a more general-purpose interface and that is more adaptable.
17:00
So, this is how the interface for Asgi looks as of Asgi 3, which is, we're done now. I mean, not we're done, but we're kind of done for the big stuff, anyway. We've got these three variables that we call into the function with, scope, receive, send. Scope is a whole bunch of state
17:23
information about the incoming connection in a dictionary with a whole bunch of keys in it. And receive and send are two channels on which the web application communicates with the web server. And you use, for
17:42
example, in the HTTP context, you'll use the receive channel to do things like pulling the body of the HTTP request. You don't want it in the scope because then you'd have to have the whole body arrive all at once, so instead you'd like to be able to stream it in, in case you need to do that. And also for sending out the outgoing HTTP response.
18:13
Asgi gives us a lot of nice things. So, obviously, we've got the potential for the performance characteristics of Async that we've
18:21
talked about. Realtime communication. So it's not just WebSockets. There's also server-sent events, which are very similar to WebSockets, but they're over HTTP only, and they are unidirectional, so just sending from the server to the clients. But they can be a nice,
18:41
simple thing to use without having to go the WebSocket routes. HTTP long polling. HTTP2 server push, where when a request is made to your web server, you've hit the home page. The web server knows, okay, I haven't got any cookies from this thing. It probably is going to need all of these other assets on the page,
19:04
and I don't want it to have to go and do a couple of different round trips before it gets them, so I'm going to preemptively start pushing these assets over the connection. I'll send back there, here's the home page, and I'm also going to start sending down my cat GIFs at the same time.
19:24
Asgi also has startup and shutdown events, which gives a more nicely managed context for running tasks within that domain than Whisky has, which doesn't have any kind of way of
19:42
communicating, okay, I'm ready to go now, or, okay, can you please start shutting things down? And actually, it's pretty powerful because it allows us to do things like build clock or timer-driven events and know that the events that we're scheduling, if they're running, then when the
20:01
server requests, when we're requested to shut down, we can wait until those events are finished, and then we can send back to the server and say, okay, I'm all finished now, and we know that we're going to terminate cleanly, which can potentially allow us to build really nice task queues and so on in a much more simple way, and it's a more
20:23
adaptable interface, right? We can potentially extend this into other protocols as well, so it's here for the long term. Where's the ASCII landscape at the moment? Okay. So, we've got several different server implementations
20:41
already. We've got Daphne, the original one, Hypercorn, somebody else, Phil Jones has been working on, and Yuvicorn is one that I've spent my time on, and we've also got lots and lots of ASCII web frameworks emerging. Starlet is the one that I've been working on, and I'm going to show you some of how that looks a bit different to Django and why that's interesting in a moment.
21:02
Django channels is slightly the odd one out on this list because that's async on the front, but threaded most of the rest of the way through, and we've also got other stuff that's starting to be developed in this area as well. So, let's, what I want to do over
21:20
the next few slides is take a look at if we're building an async web framework, what are some of the ways that we could do things a little bit differently, and I think a lot of this can feed into some of the work that we're hoping to start doing on Django over the coming months.
21:41
Now, Starlet, okay, up here, this example looks like any old standard micro web framework, but there are a few ways that it's put together that I think are a little bit interesting. Now, it's one thing that we're going to see a lot. It's ASCII all the way through. We use the ASCII interface as the primary
22:01
thing on which the stack is built, all the way right up to the, when you're working with a view, and then you're in request response, and you're dealing with requests and responses, but all the way through, every other part of the system, if you start to dig into what's happening, it's based on ASCII. And here's a good example of
22:24
that is a response in Starlet itself exposes the ASCII interface. So an instance of a response is a valid web framework. It's a very small one that just does one thing, but it is. Okay,
22:42
interesting. Okay. Just to get a bit of an idea about how some of the components look, this isn't the level that you would be working at normally. This is using requests and responses within a raw ASCII interface. Normally, you'd be working within a proper request response view,
23:01
but you can see how requests are just an interface that is instantiated over the ASCII state that you can then do stuff with. Okay. Fine. Let's have another look at ways in which we use ASCII all the way through. The
23:21
test client. The test client in Starlet is built upon requests. It is requests. It's requests, but with an adapter class, an adapter class that, instead of making raw network requests, plugs directly into ANNE,
23:46
into an ASCII framework. And that's great, because we can use our test client to test any ASCII web framework, not just Starlet,
24:01
but any of the other ones that we saw were up on the screen earlier. Or to test any micro, you know, any ASCII component as well. So here, we're just instantiating a response, and we're making a request out to it using the standard requests library with all of the standard API and
24:21
behaviors requests. The next place, we said we're using it all the way through, so, of course, we're writing ASCII middleware as well. Now, in, say, Django and lots of other web frameworks, what happens with
24:41
the HTTP dispatching is that the first thing that happens, the request comes in, we create some kind of request instance, and then we pass our request instance all the way through a middleware stack that gets request instances, calls into the next thing in the chain, and returns response instances. Why wouldn't we
25:03
want to do that? Sounds fine, sounds good. Well, what's nice about using ASCII as the middleware interface is that your middleware implementations are reusable across, again, any
25:22
ASCII web framework. They're also independently testable using the same test client that you use for testing everything else. It's also important to design things in this way because if you build your middleware as a request
25:41
response interface, what do you do when you come to web sockets? We're going to build another different type of interface. If you're working against the ASCII interface, it's much clearer how to build, for example, middleware that authenticates both HTTP and
26:01
web socket requests based on the headers in either. Okay, but as a developer, you want to be working at that level all the time. No problem. One of the things that Starlet provides is a class that you can subclass that to you, the end
26:22
developer, provides a request response interface, but to the outside world provides the ASCII interface. So when the request comes in, it creates a request instance, sends it off to the server. You call in to call next, and it does
26:43
the job of inspecting any messages coming back down and marshaling those into response instances. And that's great because you're working at the request response level, but again, you're building reusable middleware that we can share with the rest of the community and when
27:01
the rest of the community are building middleware, they can share with us. What else? Mountable apps. Top example here. If you want to build a file server in Starlet, that's what you do. You can run that top example with Daphne, with Hypercom, with Yuvicom, and that will just work.
27:25
If you want to put that within your web application and serve static files within your web application, you mount that to a particular endpoint. And again, we're building more and more reusable components. So a great example of this, you know, talking
27:43
half an hour ago about Ariadne GraphQL server. It has an ASCII interface. You can just plug it straight in, and it's not coupled to a particular web framework. It's about ASCII. Another example, class-based views.
28:02
Similar sort of thing. The class-based views in Starlet expose the ASCII interface. You can do interesting things like, you know, that allows you to build out more high-level variations on this. So if you want to build something that's like Rest Framework's
28:20
view sets or anything else like that. One of the other things that, and we'll see it again a bit later on, is a point of difference is all the way through in this style of design, we're using per component configuration.
28:41
So we're not using framework-level settings that are then action over distance picked up somewhere inside the web framework. Not quite sure where. And have some kind of effect. Hard to see as a developer if you want to kind of plumb into what's happening
29:01
here. Where is this getting used? And we're also not using application-wide settings where we're plugging all of the configuration directly into this one single application instance. So per component configuration, which, again, helps with better reusable
29:21
components across the ecosystem, helps with being able to test components in isolation, so on. So what I think is interesting about some of the design in this is, again, all stuff that I hope as we're progressing on Django can feed into
29:40
some of the ASCII work that's going on there. And it's all about the overall complexity of the stack. You've got this one single interface style that runs all the way through. Very consistent. You can use a test client with lots of different components. It's very, very composable. It's also very performant because we're not introducing any extra abstractions on
30:01
top of this interface style. Blimey. Oh, yeah, I said that I say that. We're not in the States, so nobody picks me up for it. But there we go. Okay. Async. Great. What about the database? Blimey.
30:21
Oh, God, there it is again. Okay. Django ORM, SQL alchemy are both thread synchronous APIs. And not just that, but if you go down to
30:40
the lower levels, there's something that is kind of very analogous to WSGI in a way is the Python interface that is used to separate the database driver from the higher level code that is working with that driver is also a thread synchronous interface. And we've got lots and
31:02
lots of folks who have been working in the async space developing async database drivers. But we don't have a standard interface onto them. So it's difficult to start writing tooling that works together with SQLite and Postgres and MySQL.
31:21
I've recently released a package called databases, which aims to address this. It's not analogous to DBAPI exactly because it's a slightly different level of interface. It's aimed to be something that is, you know, very developer-facing interface.
31:41
You can use it to make raw SQL queries to any of those async database drivers. You can also use it to work together with SQL alchemy core. So the table definitions and the query builder, which is an absolutely sell at all. It's not all the way to an ORM,
32:01
but it's a really productive level to be working at nonetheless. It's also great because it allows you to use SQL alchemy core. If you write your table definitions using that, you then have support for migrations using their Alembic, which is, you know, analogous to Django's
32:22
migrations, and it provides transaction support as well. And dealing with database connections sensibly handles all that sort of stuff for you. Great. So there's a low-level answer to what do we need to do in the async landing
32:40
or to address the database. But there's still a component that's missing there, which is a fully fledged ORM. So I've also released another package independent of databases but built on top of it, which is a Django-like or the
33:02
start of a Django-like ORM but asynchronous. And, again, because it's built on top of databases, we still got the migration support. It's got a very Django-like API. It's not all the way there yet, but
33:20
we've got a bunch of stuff in, so we've got all of the different filter expressions and so on. We've got support for foreign key relationships and we've got support for select-related. We don't have support for many-to-many yet or reverse foreign keys or prefetch-related. And if you're building an async
33:42
ORM, because IO always needs to be explicit, there are a few things that we need to do a little bit differently. So, for example, in the Django ORM, if you've fetched a model instance, you haven't fetched
34:01
a relationship on it, and you access that relationship on it, it will go off and generate some SQL and resolve that automatically for you. You can't do that with async. You have to either have called select-related on it in the
34:20
first place, or explicitly load it and say, I want to resolve this thing now, and it will raise an error to you otherwise. Similar stuff with paging through query sets. If you don't want to fetch the entire set of results in a query set all at once, you
34:41
need to do that explicitly, and the syntax is, it's an async iterator, so it looks like async for instance in query sets. But it's a bit different to being able to just do that implicitly in Django. As well as looking a bit
35:01
differently, there are also benefits to this explicit style. I think a very large number of people in this room will have hit the types of cases where maybe you're working with your own code base, or you're working with a code base that you've recently come into, and you go, this view is running really, really
35:22
slowly. Why is that? And you dig into it, and you find that somewhere in the template code, it's iterating over a query set, and it's accessing some relationship or some field on there that's not there, and it's generating SQL queries again and again and again. Now, in async, in a
35:44
standard style setup, you can't run database queries in a template at all. It stops you from doing that. It ensures that anything that you're accessing, you have loaded, and if you try to load something without
36:00
explicitly doing that, it will raise you a great big error. Similarly, you can't do database lookups in str. I've worked with clients who go, this bit in the admin is running incredibly slowly. Why is that? It's because when you're displaying your model instance, you're
36:21
generating SQL queries. You don't want to do that. And having that tighter control, yeah, it's a bit more to think about, but it's also this huge benefit as well. You know, people run into this with Django, and they go Django's slow. Well, it's not,
36:41
no, but it's allowing you to not look after yourself. Now, this is a bit different, okay? But I've been working with it for a while, and I really, really like it now. I really like it. What else? Yeah, there's even more to think about. So you've gone to all this trouble
37:02
of building potentially very high concurrency services. You might want to be precise about how you think about database connections and database transactions. So a really good example of this is if you are building microservices, you've got a gateway API, and
37:22
the job of the gateway API is to request comes in, make a database access in order to authenticate the user, great user's authenticated, go and send an HTTP request out to some other service, wait for the response, send it back to the end user. And what you
37:42
don't want to do if you want to be able to build very high throughput services like that is hold on to your database connection or your, especially not a database transaction, for the entire duration of that HTTP request. There's just no need. You want to acquire your
38:01
connection, do your work, let go of it, then go and make your HTTP request, because that is a really, really slow operation. You don't want to be hanging on to this valuable system resource for the whole duration of it. So, for example, databases is designed to be very liberal with acquiring and releasing connections to the connection pool unless
38:22
you are explicitly within a transaction. And there's other places to think about as well. So, if we want to have async HTTP requests, the requests library doesn't give that to us out of the box yet. I've just released a package
38:41
recently, requests async, which is requests with a different adapter that makes asynchronous network requests. Email, really, you want to make non-blocking SMTP requests. There's a great library for that already. Caching, you know, interacting with Redis or memcache.
39:02
Again, that's a network operation. I thought it was back at the stage there. Even validation. So, you're building a validation library, form validation, API validation. If you want to be able to perform any database queries within that, you're
39:21
going to need to be able to make sure that your validation library provides support for async methods as well. And stuff like password hashing. Password hashing is interesting because it's deliberately designed to run slowly. If you run something very, very,
39:40
very, very slowly in a single async task, then what happens is all of that normal very fast interleaving between all of your different tasks stops happening. And this one task is just hogging everything else up. And these other tasks are getting blocked. So, two different ways you can solve
40:00
that. Either you can make sure that your password hashing is yielding to the other tasks lots of the ways through. Or you can take a simple approach and just dispatch it off to a thread. You say, okay, go and run this thing in a thread. Don't block the main event loop. So, this is the stack of stuff that I've been working on
40:21
recently. And trying to lay a really healthy kind of groundwork for all of the async stuff that I think is about to be on the way at a very great rate. Let's take a look at how all of this stuff hangs together if
40:40
you want to start building full-stack web frameworks based on this. Don't worry if you can't read everything in the slide here. It's not so bad, right? It's just to give a bit of a flavor of a few different points of difference between what we're used to in Django and some of the
41:01
design style here. Settings. We're still pulling all of our settings together in the same place. We're still using standard 12-factor configuration style. But we're then using those settings and pulling them into the components or the resources that we're
41:21
using them within so they're less entangled in their design. Models. Kind of similar. Point here being the async landscape is really starting to mature. Type validation.
41:42
Type system is a library that handles both API validation and form rendering. Kind of similar to REST framework serializers but it's trimmed down a bit. The difference here being our validation libraries need to be able to support async methods as well. In Starlet we call them endpoints or in REST framework
42:01
or in Django views. The interesting thing to kind of note here is it's very, very clear where our database accesses are happening or network requests. So we've got some views which are not async. There's no database accesses that are happening in there. They don't need to
42:21
be async. We can see exactly where stuff's happening with the database, which is really great. Routing, pretty similar. We've talked about per component configuration and being able to mount ascii apps. Pulling it all together
42:41
we've got a single app instance at the top which ends up just being a bunch of middleware that you pulled into it. A couple of other default middlewares that it will always include because you pretty much always want them to deal with server errors or exception handling.
43:01
So the middleware and then the routing. And that's it. So we've got something that's quite Django-ish. This is very, very decoupled, low impact approach. Performs great in terms
43:22
of throughputs. As great as you could reasonably need. It's able to support web sockets or service end events. And various other stuff. Background tasks we mentioned briefly. And HTTP server push.
43:43
And it lets us do things that we just can't do with Django at the moment. So building API gateway services that can comfortably handle tens of thousands of requests per second.
44:00
Building proxy services. Building GraphQL backends with real-time subscription endpoints that can serve thousands of clients at the same time. All things that we would really like to start to be able to push Django into the realm of. And doing all the legwork
44:22
for this. And the other thing that we have is this very, very composed style. So we can start right at the bottom here. A raw ASCII interface. We can work our way gradually up using individual ASCII components. Up to using these tools
44:41
in a very micro-framework-ish way. All the way up to using them in the same sort of way as a full-stack web framework. So what does this mean for Django? A few things in tandem.
45:03
I suppose it should be two things in tandem, really. I don't know what a three-way bike's called. First of all, progressively adding ASCII into the stack. So Andrew Godwin has what I think is actually a very achievable proposal for how we would go about
45:22
getting some aspects of this into Django. Starting off by adding an ASCII interface onto Django, but running everything within thread pools beyond that. Then gradually you iterate and you build that out so that the middleware stack is ASCII-based. And at that point, if you need to be able to drop into
45:41
async in a view, then you can. Your Django components might not necessarily support it, but if you want to do a little bit, if you don't mind doing a little bit of extra work, you've got more power available to you. And then iterating on from there and looking at turning some of the
46:01
components async along the way. And the other thing, there's a lot of groundwork that's been done for this already. Things like the databases package could potentially be used in an async Django ORM. Maybe we don't need an async Django ORM. Maybe one that just dispatches into the thread pool will work equally well.
46:22
We've got a lot of groundwork laid is the point. And at the same time as all of that, pushing really hard to keep maturing the async landscape. And in particular, pushing really hard to do that in a way that is something that the whole
46:41
community can share. So getting behind ASCII as a standard because it allows us to work together really efficiently. And I think that the Python community has a really important message here, which is you know, I
47:01
don't think there's anything out there that beats Python for productivity. It's absolutely awesome. And async makes it competitive with the other big players in its zone with Node and with Go. And brings support for
47:21
real-time protocols and loads of other stuff. You know, to me, if we can reach a great level of functionality with this stuff, Python's really hitting the sweet spot there.
47:41
Yeah. I think it's a really simple message and I think it's really powerful and I think it's one that we need to start communicating to the rest of the world. Okay. Quickly, all of the Django Fellows work only ever
48:01
happens because it's sponsored. My time only happens because it's sponsored. I think that's the ask that we have when we say, hey, I want to work for your companies full-time for 50 euros a month
48:21
or 150 euros a month. You know, if your businesses can see the potential of the impact that this sort of work plus the work on rest framework, the 3.10 that's coming out soon and the open API support that's going to be in there and your companies are going to benefit from these things over the next year, the next two years, the next five
48:41
years and into the long term, I think the investment is just an absolute no-brainer. So whether that is through the DSF, through rest framework sponsorships, whether it's through community events like this or Django Girls or local events in your something, anything, it's so
49:01
important. I also think in order for us to take things to the next level, that we're going to need to find other monetization strategies as well.
49:20
And ones that benefit the community. And I think for this to happen with frameworks like Django and like Rails, they need to be truly succeeding in the product space as well. Providing great products
49:42
that are the fastest possible on-ramp for developers to get started with Django or with Rails. Give developers the ability to start mocking out your API, your API documentation, or give developers the ability to start
50:01
sketching out their admin and start putting data in there. Yes, you might be limited to a certain number of rows in there. We've got some constraints that we're not going to do it. We're only going to be with you for the prototyping stage. But the goal of our product is to lose you as a user. We want you to end up
50:21
taking complete control of the framework at the end of the day. We'll have a great big button there. Great, let's get started on my product. I'm happy with the prototyping stage. Our front-end team's been working against it. And, you know, that is the most efficient thing for us to be doing for our developers at a certain point
50:41
in the maturity of these frameworks. And, you know, if we can do it, if we can nail it, we could have a company that just works on Django or Starlets or the Python ecosystem full-time. And, you know, the more we can succeed with this,
51:01
the more developers we can bring on board. I was chatting over the slides with Carlton late last night, and we went over these last three slides and
51:20
summed them up to him at the end and said, first one is, give us your money. Next one is, here's how we make money. And the last one is, it's not about the money. Right? And it's not. It's really not. You know, the money's a tool. Okay, why are we here? Why
51:41
do we care about open source? Right? Why have we all come together? Right? Our guiding light in all of this, our thing that keeps us focused has to be, you know, impact on society, betterment of society.
52:01
There's this great quote by this, an American Trappist monk, Thomas Moore, which is, you know, if we do not do this, we may find ourselves climbing to the very top of the ladder of success, only to find that the ladder has been leaning against the wrong wall. Okay?
52:22
And if we focus on our values rather than allowing the raw power of the market to set the direction and the flow, then we change the rules of the game and you help evolve
52:42
the very currency with which the market actually trades in. We, oh, hang on a minute, I didn't show you my lovely big, that was the slide for that one. You know, it's all about taking our individual
53:02
creative spark, our individual instinctive sense of empathy, and working together as a community, as a whole, and as a society. Thank you.