django-returns¶
Meaningful Django utils based on Functional Programming.
Made possible by returns
Install¶
pip install django-returns
What¶
django-returns is a tiny layer on top of Django’s ORM that lets you opt into
returns containers when you want explicit success/failure return types
instead of exceptions.
Why¶
To bring the benefits of Functional Programming to the Django world.
- Improved predictability, understandability, maintainability.
- Safer code with type checking.
- Better error handling.
How¶
By subclassing QuerySet and applying returns decorators to its methods.
Note: the default ReturnsManager does not change Django semantics. It keeps the original methods intact and adds new ones:
*_resultvariants for sync operations (returnSuccess/Failure)*_ioresultvariants for both sync and async operations (returnIOSuccess/IOFailure)first_maybe()/last_maybe()for "might beNone" QS methods (returnSome/Nothing)
Safe ORM¶
Enable it by using the provided base model.
from django_returns.models import ReturnsModel
class Person(ReturnsModel):
name = models.CharField(max_length=255, unique=True)
Or by using the custom Manager.
from django_returns.managers import ReturnsManager
class Person(models.Model):
objects = ReturnsManager()
Basic Usage¶
Methods with the _result suffix return returns.result.Result.
from returns.result import Failure, Result, Success
def get_person_name(person_id):
result: Result = Person.objects.get_result(id=person_id)
match result:
case Success(person):
return Success(person.name)
case Failure(Person.DoesNotExist()):
return ""
IO Methods¶
Async/IO *_ioresult methods return an IO-wrapped result (IOSuccess / IOFailure).
from returns.io import unsafe_perform_io
from returns.result import Failure, Success
async def get_person_id_async(name):
io_result = await Person.objects.aget_ioresult(name=name)
result = unsafe_perform_io(io_result)
match result:
case Success(person):
return person.id
case Failure(error):
return -1