Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b9014a9
Comply with Django async syntax
Archmonger May 6, 2023
14412be
bump codecov
Archmonger May 6, 2023
a251b67
Merge remote-tracking branch 'upstream/main' into new_syntax
Archmonger May 9, 2023
e1ad78f
Add deprecation warning for async_* methods
Archmonger May 9, 2023
11de735
sort imports
Archmonger May 9, 2023
ad8684d
format
Archmonger May 9, 2023
f83bcc3
use dir instead of inspect
Archmonger May 9, 2023
9eb7f8f
fix Django warning
Archmonger May 9, 2023
7cb3938
use async wrapper
Archmonger May 9, 2023
0a30431
manually add deprecation warning
Archmonger May 9, 2023
2373de6
formatting
Archmonger May 9, 2023
83e5bb6
Attempt iter fix
Archmonger May 9, 2023
6792749
QuerySetAsync monolith: Django QuerySet doesn't support inheritance
Archmonger May 9, 2023
ffbd6aa
pin minimum channels version
Archmonger May 9, 2023
500b1f1
add django 4+ support
Archmonger May 9, 2023
e51a8ed
attempt fixing dependency hell
Archmonger May 9, 2023
cdf5189
pin python versions for django-4
Archmonger May 10, 2023
325435d
bump minimum python version
Archmonger May 10, 2023
1a0af8f
prioritize Django methods
Archmonger May 10, 2023
f28e07c
format
Archmonger May 10, 2023
eee0c29
fix legacy typo
Archmonger May 10, 2023
a92fff4
better docstring
Archmonger May 10, 2023
fb3d77b
_prioritize_django -> _prefer_django
Archmonger May 10, 2023
038c6d6
add wrappers.py
Archmonger Jul 2, 2023
5a224b3
remove useless wrapper funcs
Archmonger Jul 2, 2023
7650941
human readable log
Archmonger Jul 2, 2023
aaf7674
format and standardize readme
Archmonger Jul 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7]
python-version: ['3.10']
steps:
- uses: actions/checkout@v2

Expand Down Expand Up @@ -46,7 +46,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, '3.10']
python-version: ['3.8', '3.9', '3.10']
steps:
- uses: actions/checkout@v2

Expand Down
158 changes: 80 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
## Disclaimer: Don't use this module in production it's still in active development.

# Django Async Orm

Django module that brings async to django ORM.

# Installing

```
python -m pip install django-async-orm
```
```

then add `django_async_orm` to your `INSTALLED_APPS` list:

Expand All @@ -18,10 +20,12 @@ INSTALLED_APPS = [
'django_async_orm'
]
```

# Usage

Django Async Orm will patch all your existing models to add `async_*` prefixed methods.
To be

_note:_ Only non-existing methods will be patched.

example:

Expand All @@ -35,129 +39,127 @@ you can use it as follow:

```python
async def get_model():
return await MyModel.objects.async_get(name="something")
return await MyModel.objects.aget(name="something")
```

you can also iterate over a query set with `async for`:

```python
async def all_models():
all_result_set = await MyModel.objects.async_all()
all_result_set = await MyModel.objects.aall()
async for obj in all_result_set:
print(obj)
```

Some wrappers are also available for template rendering, form validation and login/logout


#### Async login

```python
from django_async_orm.wrappers import async_login
from django_async_orm.wrappers import alogin

async def my_async_view(request):
await async_login(request)
await alogin(request)
...
```

#### Form validation

```python

from django_async_orm.wrappers import async_form_is_valid
from django_async_orm.wrappers import aform_is_valid
async def a_view(request):
form = MyForm(request.POST)
is_valid_form = await async_form_is_valid(form)
is_valid_form = await aform_is_valid(form)
if is_valid_form:
...

```

```

# Django ORM support:

This is an on going projects, not all model methods are ported.

### Manager:

| methods | supported | comments |
|------------------------------------------|------------|----------|
| `Model.objects.async_get` | ✅ | |
| `Model.objects.async_create` | ✅ | |
| `Model.objects.async_count` | ✅ | |
| `Model.objects.async_none` | ✅ | |
| `Model.objects.async_bulk_create` | ✅ | |
| `Model.objects.async_bulk_update` | ✅ | |
| `Model.objects.async_get_or_create` | ✅ | |
| `Model.objects.async_update_or_create` | ✅ | |
| `Model.objects.async_earliest` | ✅ | |
| `Model.objects.async_latest` | ✅ | |
| `Model.objects.async_first` | ✅ | |
| `Model.objects.async_last` | ✅ | |
| `Model.objects.async_in_bulk` | ✅ | |
| `Model.objects.async_delete` | ✅ | |
| `Model.objects.async_update` | ✅ | |
| `Model.objects.async_exists` | ✅ | |
| `Model.objects.async_explain` | ✅ | |
| `Model.objects.async_raw` | ✅ | |
| `Model.objects.async_all` | ✅ | |
| `Model.objects.async_filter` | ✅ | |
| `Model.objects.async_exclude` | ✅ | |
| `Model.objects.async_complex_filter` | ✅ | |
| `Model.objects.async_union` | ✅ | |
| `Model.objects.async_intersection` | ✅ | |
| `Model.objects.async_difference` | ✅ | |
| `Model.objects.async_select_for_update` | ✅ | |
| `Model.objects.async_prefetch_related` | ✅ | |
| `Model.objects.async_annotate` | ✅ | |
| `Model.objects.async_order_by` | ✅ | |
| `Model.objects.async_distinct` | ✅ | |
| `Model.objects.async_difference` | ✅ | |
| `Model.objects.async_extra` | ✅ | |
| `Model.objects.async_reverse` | ✅ | |
| `Model.objects.async_defer` | ✅ | |
| `Model.objects.async_only` | ✅ | |
| `Model.objects.async_using` | ✅ | |
| `Model.objects.async_resolve_expression` | ✅ | |
| `Model.objects.async_ordered` | ✅ | |
| `__aiter__` | ✅ | |
| `__repr__` | ✅ | |
| `__len__` | ✅ | |
| `__getitem__` | ✅ | |
| `Model.objects.async_iterator` | ❌ | |
| methods | supported | comments |
| ----------------------------------- | --------- | -------- |
| `Model.objects.aget` | ✅ | |
| `Model.objects.acreate` | ✅ | |
| `Model.objects.acount` | ✅ | |
| `Model.objects.anone` | ✅ | |
| `Model.objects.abulk_create` | ✅ | |
| `Model.objects.abulk_update` | ✅ | |
| `Model.objects.aget_or_create` | ✅ | |
| `Model.objects.aupdate_or_create` | ✅ | |
| `Model.objects.aearliest` | ✅ | |
| `Model.objects.alatest` | ✅ | |
| `Model.objects.afirst` | ✅ | |
| `Model.objects.alast` | ✅ | |
| `Model.objects.ain_bulk` | ✅ | |
| `Model.objects.adelete` | ✅ | |
| `Model.objects.aupdate` | ✅ | |
| `Model.objects.aexists` | ✅ | |
| `Model.objects.aexplain` | ✅ | |
| `Model.objects.araw` | ✅ | |
| `Model.objects.aall` | ✅ | |
| `Model.objects.afilter` | ✅ | |
| `Model.objects.aexclude` | ✅ | |
| `Model.objects.acomplex_filter` | ✅ | |
| `Model.objects.aunion` | ✅ | |
| `Model.objects.aintersection` | ✅ | |
| `Model.objects.adifference` | ✅ | |
| `Model.objects.aselect_for_update` | ✅ | |
| `Model.objects.aprefetch_related` | ✅ | |
| `Model.objects.aannotate` | ✅ | |
| `Model.objects.aorder_by` | ✅ | |
| `Model.objects.adistinct` | ✅ | |
| `Model.objects.adifference` | ✅ | |
| `Model.objects.aextra` | ✅ | |
| `Model.objects.areverse` | ✅ | |
| `Model.objects.adefer` | ✅ | |
| `Model.objects.aonly` | ✅ | |
| `Model.objects.ausing` | ✅ | |
| `Model.objects.aresolve_expression` | ✅ | |
| `Model.objects.aordered` | ✅ | |
| `__aiter__` | ✅ | |
| `__repr__` | ✅ | |
| `__len__` | ✅ | |
| `__getitem__` | ✅ | |
| `Model.objects.aiterator` | ❌ | |

### RawQuerySet

Not supported ❌

You can still call `Model.object.async_raw()` but you will be unable to access the results.
You can still call `Model.object.araw()` but you will be unable to access the results.

### Model:

| methods | supported | comments |
|----------------------------|------------|----------|
| `Model.async_save` | ❌ | |
| `Model.async_update` | ❌ | |
| `Model.async_delete` | ❌ | |
| `...` | ❌ | |

| methods | supported | comments |
| --------------- | --------- | -------- |
| `Model.asave` | ❌ | |
| `Model.aupdate` | ❌ | |
| `Model.adelete` | ❌ | |
| `...` | ❌ | |

### User Model / Manager
| methods | supported | comments |
|----------------------------|------------|----------|
| `UserModel.is_authenticated` | ✅ | |
| `UserModel.is_super_user` | ✅ | |
| `UserModel.objects.async_create_user` | ❌ | |
| `...` | ❌ | |

| methods | supported | comments |
| --------------------------- | --------- | -------- |
| `User.is_authenticated` | ✅ | |
| `User.is_super_user` | ✅ | |
| `User.objects.acreate_user` | ❌ | |
| `...` | ❌ | |

### Foreign object lazy loading:
Not supported ❌

Not supported ❌

### Wrappers:
| methods | supported | comments |
|----------------------------|------------|----------|
| `wrappers.async_render` | ✅ | |
| `wrappers.async_login` | ✅ | |
| `wrappers.async_logout` | ✅ | |



| methods | supported | comments |
| --------- | --------- | -------- |
| `arender` | ✅ | |
| `alogin` | ✅ | |
| `alogout` | ✅ | |
2 changes: 1 addition & 1 deletion django_async_orm/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class AsyncOrmConfig(AppConfig):
name = "django_async_orm"

def ready(self):
logging.info("AsyncORM: patching models")
logging.info("Patching models to add async ORM capabilities...")
for model in apps.get_models(include_auto_created=True):
patch_manager(model)
# TODO: patch_model(model)
4 changes: 2 additions & 2 deletions django_async_orm/iter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __aiter__(self):
async def __anext__(self):
try:
element = next(self._iter)
except StopIteration:
raise StopAsyncIteration
except StopIteration as e:
raise StopAsyncIteration from e
await asyncio.sleep(0)
return element
Loading