Skip to content

Instantly share code, notes, and snippets.

@imankulov
Created July 19, 2012 05:11
Show Gist options
  • Save imankulov/3140906 to your computer and use it in GitHub Desktop.
Save imankulov/3140906 to your computer and use it in GitHub Desktop.
Django shortcut manager
# -*- coding: utf-8 -*-
from django.db import models
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
class ShortcutManager(models.Manager):
"""
Manager to get access to instances of your models with just a few keystrokes.
"""
def __init__(self, attr_name):
self._attr_name = attr_name
super(ShortcutManager, self).__init__()
def __getattr__(self, attr):
try:
return self._get_object(attr)
except (ObjectDoesNotExist, MultipleObjectsReturned), e:
raise AttributeError(e)
def __getitem__(self, key):
try:
return self._get_object(key)
except (ObjectDoesNotExist, MultipleObjectsReturned), e:
raise KeyError(e)
def __call__(self, *args, **kwargs):
try:
return self.get_query_set().get(*args, **kwargs)
except (ObjectDoesNotExist, MultipleObjectsReturned):
return None
def _get_object(self, key):
attr_object = getattr(self.model, self._attr_name, None)
if callable(attr_object):
return attr_object(key)
return self.get_query_set().get(**{self._attr_name: key})

About shortcut manager

ShortcutManager is a useful manager to get quick access to instances of your models with just a few keystrokes.

Its main purpose is not to replace standard ModelManager, but to speed up a day-to-day work in Django console.

With the shortcut manager, instead of:

>>> SomeModel.objects.get(name='foo')

you can use:

>>> SomeModel.q.foo

and this is basically the same as:

>>> SomeModel.q['foo']

Additionally, there is also a get_object_or_none interface there. Because manager has the __call__() method overriden, you can use it like this:

>>> print SomeModel.q(name='foo')
<SomeModel: ...>
>>> print SomeModel.q(name='non existent user')
None

How to define it

You can either define a model field or a model classmethod to be used in the shortcut:

# Class Foo is quite simple, and uses 'name' field to get instances

class Foo(models.Model):
    objects = models.Manager()
    q = ShortcutManager('name')
    name = models.CharField(max_length=1024)


# Class Bar is slightly more elaborated. Please note that instead of name
# of the field the name of the callable is passed to manager.
#
# Don't bother about ObjectDoesNotExist or MultipleObjectsReturned
# exceptions in the code of shortcut, they will be handled appropriately

class Bar(models.Model):
    objects = models.Manager()
    q = ShortcutManager('shortcut')
    domain = models.CharField(max_length=1024)

    @classmethod
    def shortcut(cls, key):
        if '.' not in key:
            key = '%s.example.com' % key
        return Bar.objects.get(domain=key)

Random notes

Please make sure you have defined standard Manager in your models, and made it before defining your shortcut manager. Shortcut manager has a required argument and thus cannot act as a default manager for model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment