mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 13:37:17 +02:00
724 lines
26 KiB
Python
724 lines
26 KiB
Python
"""
|
|
This implements the common managers that are used by the
|
|
abstract models in dbobjects.py (and which are thus shared by
|
|
all Attributes and TypedObjects).
|
|
|
|
"""
|
|
import shlex
|
|
from functools import update_wrapper
|
|
from django.db.models import Q
|
|
from evennia.utils import idmapper
|
|
from evennia.utils.utils import make_iter, variable_from_module, to_unicode
|
|
|
|
__all__ = ("TypedObjectManager", )
|
|
_GA = object.__getattribute__
|
|
_Tag = None
|
|
|
|
#
|
|
# Decorators
|
|
#
|
|
|
|
def returns_typeclass_list(method):
|
|
"""
|
|
Decorator: Always returns a list, even if it is empty.
|
|
|
|
"""
|
|
def func(self, *args, **kwargs):
|
|
self.__doc__ = method.__doc__
|
|
raw_queryset = kwargs.pop('raw_queryset', False)
|
|
result = method(self, *args, **kwargs)
|
|
if raw_queryset:
|
|
return result
|
|
else:
|
|
return list(result)
|
|
return update_wrapper(func, method)
|
|
|
|
|
|
def returns_typeclass(method):
|
|
"""
|
|
Decorator: Returns a single typeclass match or None.
|
|
|
|
"""
|
|
def func(self, *args, **kwargs):
|
|
self.__doc__ = method.__doc__
|
|
query = method(self, *args, **kwargs)
|
|
if hasattr(query, "__iter__"):
|
|
result = list(query)
|
|
return result[0] if result else None
|
|
else:
|
|
return query
|
|
return update_wrapper(func, method)
|
|
|
|
# Managers
|
|
|
|
class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|
"""
|
|
Common ObjectManager for all dbobjects.
|
|
|
|
"""
|
|
# common methods for all typed managers. These are used
|
|
# in other methods. Returns querysets.
|
|
|
|
|
|
# Attribute manager methods
|
|
def get_attribute(self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None):
|
|
"""
|
|
Return Attribute objects by key, by category, by value, by
|
|
strvalue, by object (it is stored on) or with a combination of
|
|
those criteria.
|
|
|
|
Attrs:
|
|
key (str, optional): The attribute's key to search for
|
|
category (str, optional): The category of the attribute(s)
|
|
to search for.
|
|
value (str, optional): The attribute value to search for.
|
|
Note that this is not a very efficient operation since it
|
|
will query for a pickled entity. Mutually exclusive to
|
|
`strvalue`.
|
|
strvalue (str, optional): The str-value to search for.
|
|
Most Attributes will not have strvalue set. This is
|
|
mutually exclusive to the `value` keyword and will take
|
|
precedence if given.
|
|
obj (Object, optional): On which object the Attribute to
|
|
search for is.
|
|
attrype (str, optional): An attribute-type to search for.
|
|
By default this is either `None` (normal Attributes) or
|
|
`"nick"`.
|
|
|
|
Returns:
|
|
attributes (list): The matching Attributes.
|
|
|
|
"""
|
|
dbmodel = self.model.__dbclass__.__name__.lower()
|
|
query = [("attribute__db_attrtype", attrtype), ("attribute__db_model", dbmodel)]
|
|
if obj:
|
|
query.append(("%s__id" % self.model.__name__.lower(), obj.id))
|
|
if key:
|
|
query.append(("attribute__db_key", key))
|
|
if category:
|
|
query.append(("attribute__db_category", category))
|
|
if strvalue:
|
|
query.append(("attribute__db_strvalue", strvalue))
|
|
elif value:
|
|
# strvalue and value are mutually exclusive
|
|
query.append(("attribute__db_value", value))
|
|
return [th.attribute for th in self.model.db_attributes.through.objects.filter(**dict(query))]
|
|
|
|
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
|
|
"""
|
|
Get a nick, in parallel to `get_attribute`.
|
|
|
|
Attrs:
|
|
key (str, optional): The nicks's key to search for
|
|
category (str, optional): The category of the nicks(s) to search for.
|
|
value (str, optional): The attribute value to search for. Note that this
|
|
is not a very efficient operation since it will query for a pickled
|
|
entity. Mutually exclusive to `strvalue`.
|
|
strvalue (str, optional): The str-value to search for. Most Attributes
|
|
will not have strvalue set. This is mutually exclusive to the `value`
|
|
keyword and will take precedence if given.
|
|
obj (Object, optional): On which object the Attribute to search for is.
|
|
|
|
Returns:
|
|
nicks (list): The matching Nicks.
|
|
|
|
"""
|
|
return self.get_attribute(key=key, category=category, value=value, strvalue=strvalue, obj=obj)
|
|
|
|
@returns_typeclass_list
|
|
def get_by_attribute(self, key=None, category=None, value=None, strvalue=None, attrtype=None):
|
|
"""
|
|
Return objects having attributes with the given key, category,
|
|
value, strvalue or combination of those criteria.
|
|
|
|
Args:
|
|
key (str, optional): The attribute's key to search for
|
|
category (str, optional): The category of the attribute
|
|
to search for.
|
|
value (str, optional): The attribute value to search for.
|
|
Note that this is not a very efficient operation since it
|
|
will query for a pickled entity. Mutually exclusive to
|
|
`strvalue`.
|
|
strvalue (str, optional): The str-value to search for.
|
|
Most Attributes will not have strvalue set. This is
|
|
mutually exclusive to the `value` keyword and will take
|
|
precedence if given.
|
|
attrype (str, optional): An attribute-type to search for.
|
|
By default this is either `None` (normal Attributes) or
|
|
`"nick"`.
|
|
|
|
Returns:
|
|
obj (list): Objects having the matching Attributes.
|
|
|
|
"""
|
|
dbmodel = self.model.__dbclass__.__name__.lower()
|
|
query = [("db_attributes__db_attrtype", attrtype), ("db_attributes__db_model", dbmodel)]
|
|
if key:
|
|
query.append(("db_attributes__db_key", key))
|
|
if category:
|
|
query.append(("db_attributes__db_category", category))
|
|
if strvalue:
|
|
query.append(("db_attributes__db_strvalue", strvalue))
|
|
elif value:
|
|
# strvalue and value are mutually exclusive
|
|
query.append(("db_attributes__db_value", value))
|
|
return self.filter(**dict(query))
|
|
|
|
def get_by_nick(self, key=None, nick=None, category="inputline"):
|
|
"""
|
|
Get object based on its key or nick.
|
|
|
|
Args:
|
|
key (str, optional): The attribute's key to search for
|
|
nick (str, optional): The nickname to search for
|
|
category (str, optional): The category of the nick
|
|
to search for.
|
|
|
|
Returns:
|
|
obj (list): Objects having the matching Nicks.
|
|
|
|
"""
|
|
return self.get_by_attribute(key=key, category=category, strvalue=nick, attrtype="nick")
|
|
|
|
# Tag manager methods
|
|
|
|
def get_tag(self, key=None, category=None, obj=None, tagtype=None, global_search=False):
|
|
"""
|
|
Return Tag objects by key, by category, by object (it is
|
|
stored on) or with a combination of those criteria.
|
|
|
|
Attrs:
|
|
key (str, optional): The Tag's key to search for
|
|
category (str, optional): The Tag of the attribute(s)
|
|
to search for.
|
|
obj (Object, optional): On which object the Tag to
|
|
search for is.
|
|
tagtype (str, optional): One of None (normal tags),
|
|
"alias" or "permission"
|
|
global_search (bool, optional): Include all possible tags,
|
|
not just tags on this object
|
|
|
|
Returns:
|
|
tag (list): The matching Tags.
|
|
|
|
"""
|
|
global _Tag
|
|
if not _Tag:
|
|
from evennia.typeclasses.models import Tag as _Tag
|
|
dbmodel = self.model.__dbclass__.__name__.lower()
|
|
if global_search:
|
|
# search all tags using the Tag model
|
|
query = [("db_tagtype", tagtype), ("db_model", dbmodel)]
|
|
if obj:
|
|
query.append(("id", obj.id))
|
|
if key:
|
|
query.append(("db_key", key))
|
|
if category:
|
|
query.append(("db_category", category))
|
|
return _Tag.objects.filter(**dict(query))
|
|
else:
|
|
# search only among tags stored on on this model
|
|
query = [("tag__db_tagtype", tagtype), ("tag__db_model", dbmodel)]
|
|
if obj:
|
|
query.append(("%s__id" % self.model.__name__.lower(), obj.id))
|
|
if key:
|
|
query.append(("tag__db_key", key))
|
|
if category:
|
|
query.append(("tag__db_category", category))
|
|
return [th.tag for th in self.model.db_tags.through.objects.filter(**dict(query))]
|
|
|
|
def get_permission(self, key=None, category=None, obj=None):
|
|
"""
|
|
Get a permission from the database.
|
|
|
|
Args:
|
|
key (str, optional): The permission's identifier.
|
|
category (str, optional): The permission's category.
|
|
obj (object, optional): The object on which this Tag is set.
|
|
|
|
Returns:
|
|
permission (list): Permission objects.
|
|
|
|
"""
|
|
return self.get_tag(key=key, category=category, obj=obj, tagtype="permission")
|
|
|
|
def get_alias(self, key=None, category=None, obj=None):
|
|
"""
|
|
Get an alias from the database.
|
|
|
|
Args:
|
|
key (str, optional): The permission's identifier.
|
|
category (str, optional): The permission's category.
|
|
obj (object, optional): The object on which this Tag is set.
|
|
|
|
Returns:
|
|
alias (list): Alias objects.
|
|
|
|
"""
|
|
return self.get_tag(key=key, category=category, obj=obj, tagtype="alias")
|
|
|
|
@returns_typeclass_list
|
|
def get_by_tag(self, key=None, category=None, tagtype=None):
|
|
"""
|
|
Return objects having tags with a given key or category or
|
|
combination of the two.
|
|
|
|
Args:
|
|
key (str, optional): Tag key. Not case sensitive.
|
|
category (str, optional): Tag category. Not case sensitive.
|
|
tagtype (str or None, optional): 'type' of Tag, by default
|
|
this is either `None` (a normal Tag), `alias` or
|
|
`permission`.
|
|
Returns:
|
|
objects (list): Objects with matching tag.
|
|
"""
|
|
dbmodel = self.model.__dbclass__.__name__.lower()
|
|
query = [("db_tags__db_tagtype", tagtype), ("db_tags__db_model", dbmodel)]
|
|
if key:
|
|
query.append(("db_tags__db_key", key.lower()))
|
|
if category:
|
|
query.append(("db_tags__db_category", category.lower()))
|
|
return self.filter(**dict(query))
|
|
|
|
def get_by_permission(self, key=None, category=None):
|
|
"""
|
|
Return objects having permissions with a given key or category or
|
|
combination of the two.
|
|
|
|
Args:
|
|
key (str, optional): Permissions key. Not case sensitive.
|
|
category (str, optional): Permission category. Not case sensitive.
|
|
Returns:
|
|
objects (list): Objects with matching permission.
|
|
"""
|
|
return self.get_by_tag(key=key, category=category, tagtype="permission")
|
|
|
|
def get_by_alias(self, key=None, category=None):
|
|
"""
|
|
Return objects having aliases with a given key or category or
|
|
combination of the two.
|
|
|
|
Args:
|
|
key (str, optional): Alias key. Not case sensitive.
|
|
category (str, optional): Alias category. Not case sensitive.
|
|
Returns:
|
|
objects (list): Objects with matching alias.
|
|
"""
|
|
return self.get_by_tag(key=key, category=category, tagtype="alias")
|
|
|
|
def create_tag(self, key=None, category=None, data=None, tagtype=None):
|
|
"""
|
|
Create a new Tag of the base type associated with this
|
|
object. This makes sure to create case-insensitive tags.
|
|
If the exact same tag configuration (key+category+tagtype+dbmodel)
|
|
exists on the model, a new tag will not be created, but an old
|
|
one returned.
|
|
|
|
|
|
Args:
|
|
key (str, optional): Tag key. Not case sensitive.
|
|
category (str, optional): Tag category. Not case sensitive.
|
|
data (str, optional): Extra information about the tag.
|
|
tagtype (str or None, optional): 'type' of Tag, by default
|
|
this is either `None` (a normal Tag), `alias` or
|
|
`permission`.
|
|
Notes:
|
|
The `data` field is not part of the uniqueness of the tag:
|
|
Setting `data` on an existing tag will overwrite the old
|
|
data field. It is intended only as a way to carry
|
|
information about the tag (like a help text), not to carry
|
|
any information about the tagged objects themselves.
|
|
|
|
"""
|
|
data = str(data) if data is not None else None
|
|
# try to get old tag
|
|
|
|
dbmodel = self.model.__dbclass__.__name__.lower()
|
|
tag = self.get_tag(key=key, category=category, tagtype=tagtype,
|
|
global_search=True)
|
|
if tag and data is not None:
|
|
# get tag from list returned by get_tag
|
|
tag = tag[0]
|
|
# overload data on tag
|
|
tag.db_data = data
|
|
tag.save()
|
|
elif not tag:
|
|
# create a new tag
|
|
global _Tag
|
|
if not _Tag:
|
|
from evennia.typeclasses.models import Tag as _Tag
|
|
tag = _Tag.objects.create(
|
|
db_key=key.strip().lower() if key is not None else None,
|
|
db_category=category.strip().lower() if category and key is not None else None,
|
|
db_data=data,
|
|
db_model=dbmodel,
|
|
db_tagtype=tagtype.strip().lower() if tagtype is not None else None)
|
|
tag.save()
|
|
return make_iter(tag)[0]
|
|
|
|
def dbref(self, dbref, reqhash=True):
|
|
"""
|
|
Determing if input is a valid dbref.
|
|
|
|
Args:
|
|
dbref (str or int): A possible dbref.
|
|
reqhash (bool, optional): If the "#" is required for this
|
|
to be considered a valid hash.
|
|
|
|
Returns:
|
|
dbref (int or None): The integer part of the dbref.
|
|
|
|
Notes:
|
|
Valid forms of dbref (database reference number) are
|
|
either a string '#N' or an integer N.
|
|
|
|
"""
|
|
if reqhash and not (isinstance(dbref, basestring) and dbref.startswith("#")):
|
|
return None
|
|
if isinstance(dbref, basestring):
|
|
dbref = dbref.lstrip('#')
|
|
try:
|
|
if int(dbref) < 0:
|
|
return None
|
|
except Exception:
|
|
return None
|
|
return dbref
|
|
|
|
@returns_typeclass
|
|
def get_id(self, dbref):
|
|
"""
|
|
Find object with given dbref.
|
|
|
|
Args:
|
|
dbref (str or int): The id to search for.
|
|
|
|
Returns:
|
|
object (TypedObject): The matched object.
|
|
|
|
"""
|
|
dbref = self.dbref(dbref, reqhash=False)
|
|
try:
|
|
return self.get(id=dbref)
|
|
except self.model.DoesNotExist:
|
|
pass
|
|
return None
|
|
|
|
def dbref_search(self, dbref):
|
|
"""
|
|
Alias to get_id.
|
|
|
|
Args:
|
|
dbref (str or int): The id to search for.
|
|
|
|
Returns:
|
|
object (TypedObject): The matched object.
|
|
|
|
"""
|
|
return self.get_id(dbref)
|
|
|
|
@returns_typeclass_list
|
|
def get_dbref_range(self, min_dbref=None, max_dbref=None):
|
|
"""
|
|
Get objects within a certain range of dbrefs.
|
|
|
|
Args:
|
|
min_dbref (int): Start of dbref range.
|
|
max_dbref (int): End of dbref range (inclusive)
|
|
|
|
Returns:
|
|
objects (list): TypedObjects with dbrefs within
|
|
the given dbref ranges.
|
|
|
|
"""
|
|
retval = super(TypedObjectManager, self).all()
|
|
if min_dbref is not None:
|
|
retval = retval.filter(id__gte=self.dbref(min_dbref, reqhash=False))
|
|
if max_dbref is not None:
|
|
retval = retval.filter(id__lte=self.dbref(max_dbref, reqhash=False))
|
|
return retval
|
|
|
|
def object_totals(self):
|
|
"""
|
|
Get info about database statistics.
|
|
|
|
Returns:
|
|
census (dict): A dictionary `{typeclass_path: number, ...}` with
|
|
all the typeclasses active in-game as well as the number
|
|
of such objects defined (i.e. the number of database
|
|
object having that typeclass set on themselves).
|
|
|
|
"""
|
|
dbtotals = {}
|
|
typeclass_paths = set(self.values_list('db_typeclass_path', flat=True))
|
|
for typeclass_path in typeclass_paths:
|
|
dbtotals[typeclass_path] = \
|
|
self.filter(db_typeclass_path=typeclass_path).count()
|
|
return dbtotals
|
|
|
|
@returns_typeclass_list
|
|
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
|
"""
|
|
Searches through all objects returning those which has a
|
|
certain typeclass. If location is set, limit search to objects
|
|
in that location.
|
|
|
|
Args:
|
|
typeclass (str or class): A typeclass class or a python path to a typeclass.
|
|
include_children (bool, optional): Return objects with
|
|
given typeclass *and* all children inheriting from this
|
|
typeclass. Mutuall exclusive to `include_parents`.
|
|
include_parents (bool, optional): Return objects with
|
|
given typeclass *and* all parents to this typeclass.
|
|
Mutually exclusive to `include_children`.
|
|
|
|
Returns:
|
|
objects (list): The objects found with the given typeclasses.
|
|
|
|
"""
|
|
|
|
if callable(typeclass):
|
|
cls = typeclass.__class__
|
|
typeclass = "%s.%s" % (cls.__module__, cls.__name__)
|
|
elif not isinstance(typeclass, basestring) and hasattr(typeclass, "path"):
|
|
typeclass = typeclass.path
|
|
|
|
# query objects of exact typeclass
|
|
query = Q(db_typeclass_path__exact=typeclass)
|
|
|
|
if include_children:
|
|
# build requests for child typeclass objects
|
|
clsmodule, clsname = typeclass.rsplit(".", 1)
|
|
cls = variable_from_module(clsmodule, clsname)
|
|
subclasses = cls.__subclasses__()
|
|
if subclasses:
|
|
for child in (child for child in subclasses if hasattr(child, "path")):
|
|
query = query | Q(db_typeclass_path__exact=child.path)
|
|
elif include_parents:
|
|
# build requests for parent typeclass objects
|
|
clsmodule, clsname = typeclass.rsplit(".", 1)
|
|
cls = variable_from_module(clsmodule, clsname)
|
|
parents = cls.__mro__
|
|
if parents:
|
|
for parent in (parent for parent in parents if hasattr(parent, "path")):
|
|
query = query | Q(db_typeclass_path__exact=parent.path)
|
|
# actually query the database
|
|
return self.filter(query)
|
|
|
|
|
|
class TypeclassManager(TypedObjectManager):
|
|
"""
|
|
Manager for the typeclasses. The main purpose of this manager is
|
|
to limit database queries to the given typeclass despite all
|
|
typeclasses technically being defined in the same core database
|
|
model.
|
|
|
|
"""
|
|
|
|
# object-manager methods
|
|
def smart_search(self, query):
|
|
"""
|
|
Search by supplying a string with optional extra search criteria to aid the query.
|
|
|
|
Args:
|
|
query (str): A search criteria that accepts extra search criteria on the
|
|
|
|
following forms: [key|alias|#dbref...] [tag==<tagstr>[:category]...] [attr==<key>:<value>:category...]
|
|
" != " != "
|
|
Returns:
|
|
matches (queryset): A queryset result matching all queries exactly. If wanting to use spaces or
|
|
==, != in tags or attributes, enclose them in quotes.
|
|
|
|
Note:
|
|
The flexibility of this method is limited by the input line format. Tag/attribute
|
|
matching only works for matching primitives. For even more complex queries, such as
|
|
'in' operations or object field matching, use the full django query language.
|
|
|
|
"""
|
|
# shlex splits by spaces unless escaped by quotes
|
|
querysplit = shlex.split(to_unicode(query, force=True))
|
|
queries, plustags, plusattrs, negtags, negattrs = [], [], [], [], []
|
|
for ipart, part in enumerate(querysplit):
|
|
key, rest = part, ""
|
|
if ":" in part:
|
|
key, rest = part.split(':', 1)
|
|
# tags are on the form tag or tag:category
|
|
if key.startswith('tag=='):
|
|
plustags.append((key[5:], rest))
|
|
continue
|
|
elif key.startswith('tag!='):
|
|
negtags.append((key[5:], rest))
|
|
continue
|
|
# attrs are on the form attr:value or attr:value:category
|
|
elif rest:
|
|
value, category = rest, ""
|
|
if ":" in rest:
|
|
value, category = rest.split(':', 1)
|
|
if key.startswith('attr=='):
|
|
plusattrs.append((key[7:], value, category))
|
|
continue
|
|
elif key.startswith('attr!='):
|
|
negattrs.append((key[7:], value, category))
|
|
continue
|
|
# if we get here, we are entering a key search criterion which
|
|
# we assume is one word.
|
|
queries.append(part)
|
|
# build query from components
|
|
query = ' '.join(queries)
|
|
#TODO
|
|
|
|
def get(self, *args, **kwargs):
|
|
"""
|
|
Overload the standard get. This will limit itself to only
|
|
return the current typeclass.
|
|
|
|
Args:
|
|
args (any): These are passed on as arguments to the default
|
|
django get method.
|
|
Kwargs:
|
|
kwargs (any): These are passed on as normal arguments
|
|
to the default django get method
|
|
Returns:
|
|
object (object): The object found.
|
|
|
|
Raises:
|
|
ObjectNotFound: The exact name of this exception depends
|
|
on the model base used.
|
|
|
|
"""
|
|
kwargs.update({"db_typeclass_path":self.model.path})
|
|
return super(TypeclassManager, self).get(**kwargs)
|
|
|
|
def filter(self, *args, **kwargs):
|
|
"""
|
|
Overload of the standard filter function. This filter will
|
|
limit itself to only the current typeclass.
|
|
|
|
Args:
|
|
args (any): These are passed on as arguments to the default
|
|
django filter method.
|
|
Kwargs:
|
|
kwargs (any): These are passed on as normal arguments
|
|
to the default django filter method.
|
|
Returns:
|
|
objects (queryset): The objects found.
|
|
|
|
"""
|
|
kwargs.update({"db_typeclass_path":self.model.path})
|
|
return super(TypeclassManager, self).filter(*args, **kwargs)
|
|
|
|
def all(self):
|
|
"""
|
|
Overload method to return all matches, filtering for typeclass.
|
|
|
|
Returns:
|
|
objects (queryset): The objects found.
|
|
|
|
"""
|
|
return super(TypeclassManager, self).all().filter(db_typeclass_path=self.model.path)
|
|
|
|
def first(self):
|
|
"""
|
|
Overload method to return first match, filtering for typeclass.
|
|
|
|
Returns:
|
|
object (object): The object found.
|
|
|
|
Raises:
|
|
ObjectNotFound: The exact name of this exception depends
|
|
on the model base used.
|
|
|
|
"""
|
|
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).first()
|
|
|
|
def last(self):
|
|
"""
|
|
Overload method to return last match, filtering for typeclass.
|
|
|
|
Returns:
|
|
object (object): The object found.
|
|
|
|
Raises:
|
|
ObjectNotFound: The exact name of this exception depends
|
|
on the model base used.
|
|
|
|
"""
|
|
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).last()
|
|
|
|
def count(self):
|
|
"""
|
|
Overload method to return number of matches, filtering for typeclass.
|
|
|
|
Returns:
|
|
integer : Number of objects found.
|
|
|
|
"""
|
|
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).count()
|
|
|
|
def _get_subclasses(self, cls):
|
|
"""
|
|
Recursively get all subclasses to a class.
|
|
|
|
Args:
|
|
cls (classoject): A class to get subclasses from.
|
|
"""
|
|
all_subclasses = cls.__subclasses__()
|
|
for subclass in all_subclasses:
|
|
all_subclasses.extend(self._get_subclasses(subclass))
|
|
return all_subclasses
|
|
|
|
def get_family(self, **kwargs):
|
|
"""
|
|
Variation of get that not only returns the current typeclass
|
|
but also all subclasses of that typeclass.
|
|
|
|
Kwargs:
|
|
kwargs (any): These are passed on as normal arguments
|
|
to the default django get method.
|
|
Returns:
|
|
objects (list): The objects found.
|
|
|
|
Raises:
|
|
ObjectNotFound: The exact name of this exception depends
|
|
on the model base used.
|
|
|
|
"""
|
|
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
|
for cls in self._get_subclasses(self.model)]
|
|
kwargs.update({"db_typeclass_path__in":paths})
|
|
return super(TypeclassManager, self).get(**kwargs)
|
|
|
|
def filter_family(self, *args, **kwargs):
|
|
"""
|
|
Variation of filter that allows results both from typeclass
|
|
and from subclasses of typeclass
|
|
|
|
Args:
|
|
args (any): These are passed on as arguments to the default
|
|
django filter method.
|
|
Kwargs:
|
|
kwargs (any): These are passed on as normal arguments
|
|
to the default django filter method.
|
|
Returns:
|
|
objects (list): The objects found.
|
|
|
|
"""
|
|
# query, including all subclasses
|
|
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
|
for cls in self._get_subclasses(self.model)]
|
|
kwargs.update({"db_typeclass_path__in":paths})
|
|
return super(TypeclassManager, self).filter(*args, **kwargs)
|
|
|
|
def all_family(self):
|
|
"""
|
|
Return all matches, allowing matches from all subclasses of
|
|
the typeclass.
|
|
|
|
Returns:
|
|
objects (list): The objects found.
|
|
|
|
"""
|
|
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
|
for cls in self._get_subclasses(self.model)]
|
|
return super(TypeclassManager, self).all().filter(db_typeclass_path__in=paths)
|
|
|
|
|