7 ms·
The most anticipated Django release for me personally. Async ORM access is a massive quality of life improvememt, same for async CBV. The later is also a blocke
by WhatsName 4y ago
The most anticipated Django release for me personally. Async ORM access is a massive quality of life improvememt, same for async CBV. The later is also a blocker for Django Rest Framework going async.
Sure most CRUD applications work perfectly fine using WSGI, but for anyone using other protocols like WS or MQTT in their app this is kind of a big deal.
- syrusakbary 4y agoI completely agree. I have been using GraphQL in Django with WebSockets and ASGI and it was a bit of pain in the ass to get everything working, but with this changes things will get much smoother. Great work Django team!
- WhyNotHugo 4y agoAlso, async views allow for better scaling. Say your view needs to make an API call to a third party service within a request-response cycle. Currently, this will block an entire worker/thread while doing a blocking request. With async, we can use async HTTP libraries and scale these WAY better.
- BozeWolf 4y agoOr just run 20 workers and let the OS handle async. OSes are pretty good at this. Async is pretty hard to reason about. Async is beneficial when you make multiple blocking (http) request to a resource at the same time and later fold that into one response. Parallel stuff. Or when you are forced to run a single thread. Or when you are memory bound. Reality is that most requests depend on previous requests quite often. In the latter case there is no benefit in terms of speed for the user. I know this is unpopular opinion though :-)
- ramraj07 4y agoMight be unpopular but still good to stick to it. I tend to associate excessive enthusiasm for pythons async await framework as a sign of immaturity and potential for doing things without understanding them fully. I’d never trust async code from anyone except the best python engineers. Most of them out there can’t even debug linear code, adding async to the mix only makes it worse. At least you can trust the time stamps.
- BozeWolf 4y agoOr when accidentally some blocking database driver is used, even when django's ORM is async, a query with mongodb's driver is not async. Or just the filesystem... This harms performance badly, especially if the idea was to run only a few threads. Other than that, it has benefits too! :-)
- mrmikardo 4y agoAnd indeed, there's an important caveat in the Django 4.1 docs; Note that, at this stage, the underlying database operations remain synchronous, with contributions ongoing to push asynchronous support down into the SQL compiler, and integrate asynchronous database drivers.... https://docs.djangoproject.com/en/4.1/releases/4.1/#asynchronous-orm-interface https://docs.djangoproject.com/en/4.1/releases/4.1/#asynchro...
- coldtea 4y ago>I tend to associate excessive enthusiasm for pythons async await framework as a sign of immaturity and potential for doing things without understanding them fully. Couldn't it be the inverse? I.e. your inexeperience with async code in other languages, and not understanding it fully, translating into "new thing aversion"?
- hansonkd13 4y agoI think my experience in async in other languages has shown how rough async in Python is. Unless async is the default python, it will always be an after thought and introduce needless complexity when working on large projects that require a lot of external libs.
- maxmalysh 4y ago> Or just run 20 workers and let the OS handle async. OSes are pretty good at this. Async is pretty hard to reason about. def slow_sync_view(request): # these requests won't be executed in parallel; # async version could eliminate this extra latency foo = requests.get('https://www.google.com/humans.txt').text bar = requests.get('https://checkip.amazonaws.com').text return HttpResponse(f'{foo}\n{bar}')
- pdhborges 4y agoI think you are being down voted because a straight port of this code to async would still run one request after the other. You would have to queue one task for each request in the event loop and then await for them both to gain some parallelism in the I/O section of the code.
- KptMarchewa 4y agoBasic concurrent.futures.ThreadPoolExecutor solves this problem. https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor https://docs.python.org/3/library/concurrent.futures.html#co...
- bpicolo 4y agoJava's Loom model really does feel like the future of concurrency in many ways.
- chpmrc 4y agoWhy would you block a process that could use CPU cycles to do something useful just to wait on I/O? With the right primitives async is not "hard" nor inconvenient. Maybe you're referring to concurrency?
- BozeWolf 4y agoNo I am referring to async, really. Accidentally blocking operations like open() or psycopg or mongodb or some included library which (accidentally) uses any of that stuff. Basically any library requiring requests is not usable. Or worse: open(). It can be hard to determine if something is doing something blocking and if it is, it is hard to debug. Especially in python world which, unlike javascript, was not async from the start.
- chpmrc 4y agoI don't understand, are you saying async is hard or that a poor implementation is a source of issues (e.g. async function that calls sync primitives)? Because I totally agree with the latter but I have no idea what "hard" means. Very little changes in terms of syntax (assuming support for async/await ops) or reasoning.
- JimDabell 4y ago> Or just run 20 workers and let the OS handle async. That just means you can only handle 20 concurrent requests before performance drops off a cliff. If the third-party service you are talking to is slow, then you’ll just end up with 20 workers all waiting for the service to respond, while other requests pile up. With async, those workers could still be handling other requests. Adding more workers because you are blocking on i/o works for low traffic services, not for anything remotely busy.
- BozeWolf 4y agoAgree! Up the number of workers to 40, fix your application in another way... or indeed go with async stuff! ;-) I was just saying that async quite often is not of much help and just complicates things. Of course it has its use! Your case is a great example of converting a django view into an async view.
- ElectricalUnion 4y ago> Adding more workers because you are blocking on i/o works for low traffic services, not for anything remotely busy. Yes. That just means in very bad cases, you can only handle 1 "concurrent request" before performance drops off a cliff. If the third-party service you are talking to is that slow, then you’ll just end up with bufferbloat (high latency in hidden queues) waiting for the service to respond, requests piling up. With async, unless you know what you're doing and handle back pressure, work pile up even worse, the service stops working and you get 0 throughput instead.
- redox99 4y agoSo now if the requests become slow because of the third party or whatever, and take 1 second each, you have a max performance of 20 rps. With async instead you would still be able to handle thousands of rps.
- westurner 4y ago## Asynchronous ORM interface https://docs.djangoproject.com/en/4.1/releases/4.1/#asynchronous-orm-interface https://docs.djangoproject.com/en/4.1/releases/4.1/#asynchro... : `QuerySet` now provides an asynchronous interface for all data access operations. These are named as-per the existing synchronous operations but with an `a` prefix, for example `acreate()`, `aget()`, and so on. > The new interface allows you to write asynchronous code without needing to wrap ORM operations in `sync_to_async()`: async for author in Author.objects.filter(name__startswith="A"): book = await author.books.afirst() > Note that, at this stage, the underlying database operations remain synchronous, with contributions ongoing to push asynchronous support down into the SQL compiler, and integrate asynchronous database drivers. The new asynchronous queryset interface currently encapsulates the necessary sync_to_async() operations for you, and will allow your code to take advantage of developments in the ORM’s asynchronous support as it evolves. […] See Asynchronous queries for details and limitations. ## Asynchronous handlers for class-based views > View subclasses may now define async HTTP method handlers: import asyncio from django.http import HttpResponse from django.views import View class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!")
- aynyc 4y agoI don't fully understand the sync_to_async() operation here. So the underlying database is not async, then is Django just tossing the sync DB call onto a thread or something?
- tgv 4y agoSeriously: why use Django for a REST-like service? I inherited an application that (probably) evolved from form-based to REST with a JS frontend, and I fail to see the point. There's a model, a serializer, handlers to implement relations, and multiple views per data type. It's so much overhead, and everything has to be kept in sync.
- varispeed 4y agoIt all depends how it is written. While Django and REST is quite strongly opinionated, you can still make it difficult to maintain if you want to. That being said, Django REST allows you to move fast. It's very very easy to knock out a REST API and data models plus some basic admin panel. Once your API matures - you can then reimplement it in Go or other platform.
- giancarlostoro 4y agoI went with Django Rest Framework when I used it for a project because it provided things I would otherwise spend says implementing out of the box. The one thing I definitely did implement for myself was filtering, the built-in stuff was kind of mediocre for our needs, outside of that I want to say we left pagination and everything else as-is. It was a bit of a nightmare to look up documentation on though I will admit, if you don't know the Google Buzzword Soup you got to look up. Previously to that I was using CherryPy and building my entire kitchen sink myself, so it had nice moments and bad moments, but it definitely saved me on time and effort. You typically do Django + REST because you are already comfortable with Django or because you were already using it, although I could argue, you could consider making your API project stand alone and using CherryPy or even FastAPI for a much nicer experience. The downside there being you wouldn't be using Django's ORM. I really do wish Django's ORM would be spun off into a stand alone project that Django then imports, so anyone else can use it in other non-django specific projects.
- znpy 4y agoI remember watching a beautiful talk from some pycon whose details I can’t remember about using django as if it was a micro-framework. It basically boils down to rejecting the folder structure that django-admin sets up for you, importing stuff yourself and doing some basic initialisation/configuration. Once you do that, django kinda somehow behaves like a micro-framework, with the significant difference that you can import and use the advanced features if you want/need to.
- collinmanderson 4y ago> for anyone using other protocols like WS Yes, if you do WebSockets, async really is a must if you don't want to have one thread per active connection. Each thread takes 8mb of virtual memory, not sure how much actual memory. It's also nice for a backend that's doing a lot of proxying apis to another backend.