Skip to content

Instantly share code, notes, and snippets.

@mattmcc
Created January 1, 2013 01:49
Show Gist options
  • Save mattmcc/4424662 to your computer and use it in GitHub Desktop.
Save mattmcc/4424662 to your computer and use it in GitHub Desktop.
Preliminary ducktyping of ManyToManyField using django-orm-extensions' ArrayField and storing a list of PKs.
class QueryList(list):
"""
A list of primary keys for a specified model which can act as a QuerySet
Takes a ``model`` keyword argument indicating which model the PKs are
associated with.
"""
def __init__(self, *args, **kwargs):
self.model = kwargs.pop('model')
super(QueryList, self).__init__(*args, **kwargs)
def get_empty_query_set(self):
from django.db.models.query import EmptyQuerySet
return EmptyQuerySet(self.model)
# TODO: We should have access to the parent instance so that we can
# use a subquery.
def get_query_set(self):
# TODO: Importing this at the module level is causing DB settings
# to be loaded before local_settings are applied
from django.db.models.query import QuerySet
return QuerySet(self.model).filter(pk__in=self)
def none(self):
return self.get_empty_query_set()
def all(self):
return self.get_query_set()
def count(self):
return self.get_query_set().count()
def distinct(self, *args, **kwargs):
return self.get_query_set().distinct(*args, **kwargs)
def filter(self, *args, **kwargs):
return self.get_query_set().filter(*args, **kwargs)
def exclude(self, *args, **kwargs):
return self.get_query_set().exclude(*args, **kwargs)
def iterator(self, *args, **kwargs):
return self.get_query_set().iterator(*args, **kwargs)
def order_by(self, *args, **kwargs):
return self.get_query_set().order_by(*args, **kwargs)
def exists(self, *args, **kwargs):
return self.get_query_set().exists(*args, **kwargs)
from django_orm.postgresql.fields.arrays import ArrayField
from .datastructures import QueryList
class ManyToManyArrayField(ArrayField):
# NOTE: 'to' isn't really optional, but we weren't able to make South
# cooperate with it as a positional argument.
def __init__(self, to=None, *args, **kwargs):
self.to = to
super(ManyToManyArrayField, self).__init__(self, *args, **kwargs)
def to_python(self, value):
if value is None:
value = []
return QueryList(value, model=self.to)
add_introspection_rules([
(
[ManyToManyArrayField],
[],
{
'to': ['to', {}],
'dbtype': ["_array_type", {"default" : "int"}]
},
),
], ['thinkspace\.lib\.db\.fields\.ManyToManyArrayField']
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment