13👍
Looks like this snippet provides a solution to your situation: Custom managers with chainable filters.
32👍
This is how you chain custom methods on custom manager ie: Post.objects.by_author(user=request.user).published()
from django.db.models.query import QuerySet
class PostMixin(object):
def by_author(self, user):
return self.filter(user=user)
def published(self):
return self.filter(published__lte=datetime.now())
class PostQuerySet(QuerySet, PostMixin):
pass
class PostManager(models.Manager, PostMixin):
def get_query_set(self):
return PostQuerySet(self.model, using=self._db)
- ImportError: cannot import name "urandom"
- Moving from direct_to_template to new TemplateView in Django
15👍
Just a code example using the new as_manager() method (see update information from @zzart.
class MyQuerySet(models.query.QuerySet):
def randomize(self):
count = self.aggregate(count=Count('id'))['count']
random_index = random.randint(0, count - 1)
return self.all()[random_index]
class MyModel(models.Model):
.....
.....
objects = MyQuerySet.as_manager()
.....
.....
And then you will be able to use something like this in your code:
MyModel.objects.filter(age__gt=16).randomize()
As you can see, the new as_manager() is really neat:)
- How should multiple Django apps communicate with each other?
- How to specify which eth interface Django test server should listen on?
- Use a django built in filter in code (outside of a template)
- How to ensure task execution order per user using Celery, RabbitMQ and Django?
2👍
Given that you have an existing models.Manager
and you don’t want to expose some of the manager method to a chainable queryset, you can use Manager.from_queryset(QuerySet)()
.
So, you could still place all your chainable queryset method inside the QuerySet and your manager method independently.
Example given in the official site.
Snippet from Django Docs
class BaseManager(models.Manager):
# Available only on Manager.
def manager_only_method(self):
return
class CustomQuerySet(models.QuerySet):
# Available on both Manager and QuerySet.
def manager_and_queryset_method(self):
return
# Available only on QuerySet.
def _private_method(self):
return
CustomManager = BaseManager.from_queryset(CustomQuerySet)
class MyModel(models.Model):
objects = CustomManager()
- Pagination and get parameters
- Django Can't Find My Templates
- Deploying django in a production server
- Using Django's built in web server in a production environment
- Using Django view variables inside templates
0👍
How about something like below which creates the custom QuerySet dynamically and allows us to ‘transplant’ our custom queries onto the returned QuerySet instance:
class OfferManager(models.Manager):
"""
Additional methods / constants to Offer's objects manager
"""
### Model (db table) wide constants - we put these and
### not in model definition to avoid circular imports.
### One can access these constants through like
<foo>.objects.STATUS_DISABLED or ImageManager.STATUS_DISABLED
STATUS_DISABLED = 0
...
STATUS_CHOICES = (
(STATUS_DISABLED, "Disabled"),
(STATUS_ENABLED, "Enabled"),
(STATUS_NEGOTIATED, "Negotiated"),
(STATUS_ARCHIVED, "Archived"),
)
...
# we keep status and filters naming a little different as
# it is not one-to-one mapping in all situations
QUERYSET_PUBLIC_KWARGS = {'status__gte': STATUS_ENABLED}
QUERYSET_ACTIVE_KWARGS = {'status': STATUS_ENABLED}
def get_query_set(self):
""" our customized method which transpalats manager methods
as per get_query_set.<method_name> = <method> definitions """
CustomizedQuerySet = QuerySet
for name, function in self.get_query_set.__dict__.items():
setattr(CustomizedQuerySet, name, function)
return CustomizedQuerySet(self.model, using=self._db)
def public(self):
""" Returns all entries accessible through front end site"""
return self.all().filter(**OfferManager.QUERYSET_PUBLIC_KWARGS)
get_query_set.public = public # will tranplat the function onto the
# returned QuerySet instance which
# means 'self' changes depending on context.
def active(self):
""" returns offers that are open to negotiation """
return self.public().filter(**OfferManager.QUERYSET_ACTIVE_KWARGS)
get_query_set.active = active
...
More polished version of this method and django ticket here: https://code.djangoproject.com/ticket/20625.