Managers¶
The managers are a great tool that Edgy offers. Heavily inspired by Django, the managers allow you to build unique tailored queries ready to be used by your models.
Edgy by default uses the the manager called query
which it makes it simple to understand.
Let us see an example.
import edgy
from edgy import Database, Registry
database = Database("sqlite:///db.sqlite")
models = Registry(database=database)
class User(edgy.Model):
name: str = edgy.CharField(max_length=255)
email: str = edgy.EmailField(max_length=70)
is_active: bool = edgy.BooleanField(default=True)
class Meta:
registry = models
unique_together = ["name", "email"]
# Using ipython that supports await
# Don't use this in production! Use Alembic or any tool to manage
# The migrations for you
await models.create_all() # noqa
await User.query.create(name="Edgy", email="foo@bar.com") # noqa
user = await User.query.get(id=1) # noqa
# User(id=1)
When querying the User
table, the query
(manager) is the default and should be always
presented when doing it so.
Custom manager¶
It is also possible to have your own custom managers and to do it so, you should inherit
the Manager class and override the get_queryset()
.
For those familiar with Django managers, the principle is exactly the same. 😀
The managers must be type annotated ClassVar or an ImproperlyConfigured
exception will be raised.
from typing import ClassVar
import edgy
from edgy import Manager, QuerySet
class InactiveManager(Manager):
"""
Custom manager that will return only active users
"""
def get_queryset(self) -> "QuerySet":
queryset = super().get_queryset().filter(is_active=False)
return queryset
class User(edgy.Model):
# Add the new manager
inactives: ClassVar[Manager] = InactiveManager()
Let us now create new manager and use it with our previous example.
from typing import ClassVar
import edgy
from edgy import Database, Manager, QuerySet, Registry
database = Database("sqlite:///db.sqlite")
models = Registry(database=database)
class InactiveManager(Manager):
"""
Custom manager that will return only active users
"""
def get_queryset(self) -> "QuerySet":
queryset = super().get_queryset().filter(is_active=False)
return queryset
class User(edgy.Model):
name: str = edgy.CharField(max_length=255)
email: str = edgy.EmailField(max_length=70)
is_active: bool = edgy.BooleanField(default=True)
# Add the new manager
inactives: ClassVar[Manager] = InactiveManager()
class Meta:
registry = models
unique_together = ["name", "email"]
# Using ipython that supports await
# Don't use this in production! Use Alembic or any tool to manage
# The migrations for you
await models.create_all() # noqa
# Create an inactive user
await User.query.create(name="Edgy", email="foo@bar.com", is_active=False) # noqa
# You can also create a user using the new manager
await User.inactives.create(name="Another Edgy", email="bar@foo.com", is_active=False) # noqa
# Querying using the new manager
user = await User.inactives.get(email="foo@bar.com") # noqa
# User(id=1)
user = await User.inactives.get(email="bar@foo.com") # noqa
# User(id=2)
# Create a user using the default manager
await User.query.create(name="Edgy", email="user@edgy.com") # noqa
# Querying all inactives only
users = await User.inactives.all() # noqa
# [User(id=1), User(id=2)]
# Querying them all
user = await User.query.all() # noqa
# [User(id=1), User(id=2), User(id=3)]
These managers can be as complex as you like with as many filters as you desire. What you need is
simply override the get_queryset()
and add it to your models.
Override the default manager¶
Overriding the default manager is also possible by creating the custom manager and overriding
the query
manager.
from typing import ClassVar
import edgy
from edgy import Database, Manager, QuerySet, Registry
database = Database("sqlite:///db.sqlite")
models = Registry(database=database)
class InactiveManager(Manager):
"""
Custom manager that will return only active users
"""
def get_queryset(self) -> "QuerySet":
queryset = super().get_queryset().filter(is_active=False)
return queryset
class User(edgy.Model):
name: str = edgy.CharField(max_length=255)
email: str = edgy.EmailField(max_length=70)
is_active: bool = edgy.BooleanField(default=True)
# Add the new manager
query: ClassVar[Manager] = InactiveManager()
class Meta:
registry = models
unique_together = ["name", "email"]
# Using ipython that supports await
# Don't use this in production! Use Alembic or any tool to manage
# The migrations for you
await models.create_all() # noqa
# Create an inactive user
await User.query.create(name="Edgy", email="foo@bar.com", is_active=False) # noqa
# You can also create a user using the new manager
await User.query.create(name="Another Edgy", email="bar@foo.com", is_active=False) # noqa
# Create a user using the default manager
await User.query.create(name="Edgy", email="user@edgy.com") # noqa
# Querying them all
user = await User.query.all() # noqa
# [User(id=1), User(id=2)]
Warning
Be careful when overriding the default manager as you might not get all the results from the
.all()
if you don't filter properly.