Fixed correct and separate handling of database model bases as compared to its proxy classes using different managers for each type (e.g. ObjectDB.objects.all() will return all ObjectDB instances(including proxy instances) whereas Object.objects.all() will only return Objects)

This commit is contained in:
Griatch 2014-12-22 08:54:53 +01:00
parent 554d1b9834
commit 2ee9e62336
15 changed files with 105 additions and 79 deletions

View file

@ -5,6 +5,7 @@ See objects.objects for more information on Typeclassing.
""" """
from src.typeclasses.models import TypeclassBase from src.typeclasses.models import TypeclassBase
from src.comms.models import Msg, TempMsg, ChannelDB from src.comms.models import Msg, TempMsg, ChannelDB
from src.comms.managers import ChannelManager
from src.utils import logger from src.utils import logger
from src.utils.utils import make_iter from src.utils.utils import make_iter
@ -15,6 +16,7 @@ class Channel(ChannelDB):
types of communication channels. types of communication channels.
""" """
__metaclass__ = TypeclassBase __metaclass__ = TypeclassBase
objects = ChannelManager()
# helper methods, for easy overloading # helper methods, for easy overloading

View file

@ -4,7 +4,8 @@ These managers handles the
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
from src.typeclasses.managers import TypedObjectManager, returns_typeclass_list, returns_typeclass from src.typeclasses.managers import (TypedObjectManager, TypeclassManager,
returns_typeclass_list, returns_typeclass)
_GA = object.__getattribute__ _GA = object.__getattribute__
_PlayerDB = None _PlayerDB = None
@ -251,7 +252,7 @@ class MsgManager(models.Manager):
# Channel manager # Channel manager
# #
class ChannelManager(TypedObjectManager): class ChannelDBManager(TypedObjectManager):
""" """
This ChannelManager implements methods for searching This ChannelManager implements methods for searching
and manipulating Channels directly from the database. and manipulating Channels directly from the database.
@ -373,6 +374,9 @@ class ChannelManager(TypedObjectManager):
for a in channel.aliases.all()]] for a in channel.aliases.all()]]
return channels return channels
class ChannelManager(ChannelDBManager, TypeclassManager):
pass
# #
# PlayerChannelConnection manager # PlayerChannelConnection manager

View file

@ -22,7 +22,7 @@ be able to delete connections on the fly).
from datetime import datetime from datetime import datetime
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from src.typeclasses.models import TypedObject, TagHandler, AttributeHandler, AliasHandler from src.typeclasses.models import TypedObject
from src.utils.idmapper.models import SharedMemoryModel from src.utils.idmapper.models import SharedMemoryModel
from src.comms import managers from src.comms import managers
from src.comms.managers import identify_object from src.comms.managers import identify_object
@ -356,7 +356,7 @@ class ChannelDB(TypedObject):
related_name="subscription_set", null=True, verbose_name='subscriptions', db_index=True) related_name="subscription_set", null=True, verbose_name='subscriptions', db_index=True)
# Database manager # Database manager
objects = managers.ChannelManager() objects = managers.ChannelDBManager()
_typeclass_paths = settings.CHANNEL_TYPECLASS_PATHS _typeclass_paths = settings.CHANNEL_TYPECLASS_PATHS
_default_typeclass_path = settings.BASE_CHANNEL_TYPECLASS or "src.comms.comms.Channel" _default_typeclass_path = settings.BASE_CHANNEL_TYPECLASS or "src.comms.comms.Channel"

View file

@ -6,7 +6,7 @@ Also, the initiated object manager is available as src.objects.manager.
""" """
from src.objects.objects import * #from src.objects.objects import *
from src.objects.models import ObjectDB from src.objects.models import ObjectDB
manager = ObjectDB.objects manager = ObjectDB.objects

View file

@ -5,7 +5,7 @@ from itertools import chain
from django.db.models import Q from django.db.models import Q
from django.conf import settings from django.conf import settings
from django.db.models.fields import exceptions from django.db.models.fields import exceptions
from src.typeclasses.managers import TypedObjectManager from src.typeclasses.managers import TypedObjectManager, TypeclassManager
from src.typeclasses.managers import returns_typeclass, returns_typeclass_list from src.typeclasses.managers import returns_typeclass, returns_typeclass_list
from src.utils import utils from src.utils import utils
from src.utils.utils import to_unicode, is_iter, make_iter, string_partial_matching from src.utils.utils import to_unicode, is_iter, make_iter, string_partial_matching
@ -22,7 +22,7 @@ _ATTR = None
_AT_MULTIMATCH_INPUT = utils.variable_from_module(*settings.SEARCH_AT_MULTIMATCH_INPUT.rsplit('.', 1)) _AT_MULTIMATCH_INPUT = utils.variable_from_module(*settings.SEARCH_AT_MULTIMATCH_INPUT.rsplit('.', 1))
class ObjectManager(TypedObjectManager): class ObjectDBManager(TypedObjectManager):
""" """
This ObjectManager implementes methods for searching This ObjectManager implementes methods for searching
and manipulating Objects directly from the database. and manipulating Objects directly from the database.
@ -413,3 +413,6 @@ class ObjectManager(TypedObjectManager):
""" """
self.filter(db_sessid__isnull=False).update(db_sessid=None) self.filter(db_sessid__isnull=False).update(db_sessid=None)
class ObjectManager(ObjectDBManager, TypeclassManager):
pass

View file

@ -20,7 +20,7 @@ from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from src.typeclasses.models import TypedObject, NickHandler from src.typeclasses.models import TypedObject, NickHandler
from src.objects.manager import ObjectManager from src.objects.manager import ObjectDBManager
from src.players.models import PlayerDB from src.players.models import PlayerDB
from src.commands.cmdsethandler import CmdSetHandler from src.commands.cmdsethandler import CmdSetHandler
from src.commands import cmdhandler from src.commands import cmdhandler
@ -171,7 +171,7 @@ class ObjectDB(TypedObject):
help_text="optional python path to a cmdset class.") help_text="optional python path to a cmdset class.")
# Database manager # Database manager
objects = ObjectManager() objects = ObjectDBManager()
# caches for quick lookups of typeclass loading. # caches for quick lookups of typeclass loading.
_typeclass_paths = settings.OBJECT_TYPECLASS_PATHS _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS

View file

@ -17,6 +17,7 @@ they control by simply linking to a new object's user property.
from django.conf import settings from django.conf import settings
from src.typeclasses.models import TypeclassBase from src.typeclasses.models import TypeclassBase
from src.objects.manager import ObjectTypeclassManager
from src.objects.models import ObjectDB from src.objects.models import ObjectDB
from src.commands import cmdset, command from src.commands import cmdset, command
from src.utils.logger import log_depmsg from src.utils.logger import log_depmsg
@ -39,6 +40,7 @@ class Object(ObjectDB):
""" """
__metaclass__ = TypeclassBase __metaclass__ = TypeclassBase
objects = ObjectTypeclassManager()
# __init__ is only defined here in order to present docstring to API. # __init__ is only defined here in order to present docstring to API.
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View file

@ -7,7 +7,7 @@ Also, the initiated object manager is available as src.players.manager.
""" """
from src.players.player import * #from src.players.player import *
from src.players.models import PlayerDB from src.players.models import PlayerDB
manager = PlayerDB.objects manager = PlayerDB.objects

View file

@ -5,7 +5,8 @@ The managers for the custom Player object and permissions.
import datetime import datetime
from django.contrib.auth.models import UserManager from django.contrib.auth.models import UserManager
#from functools import update_wrapper #from functools import update_wrapper
from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager from src.typeclasses.managers import (returns_typeclass_list, returns_typeclass,
TypedObjectManager, TypeclassManager)
#from src.utils import logger #from src.utils import logger
__all__ = ("PlayerManager",) __all__ = ("PlayerManager",)
@ -14,7 +15,7 @@ __all__ = ("PlayerManager",)
# Player Manager # Player Manager
# #
class PlayerManager(TypedObjectManager, UserManager): class PlayerDBManager(TypedObjectManager, UserManager):
""" """
This PlayerManager implements methods for searching This PlayerManager implements methods for searching
and manipulating Players directly from the database. and manipulating Players directly from the database.
@ -149,3 +150,6 @@ class PlayerManager(TypedObjectManager, UserManager):
if old_character and delete_old_character: if old_character and delete_old_character:
old_character.delete() old_character.delete()
return True return True
class PlayerManager(PlayerDBManager, TypeclassManager):
pass

View file

@ -21,7 +21,7 @@ from django.db import models
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from src.players import manager from src.players.manager import PlayerDBManager
from src.scripts.models import ScriptDB from src.scripts.models import ScriptDB
from src.typeclasses.models import (TypedObject, NickHandler) from src.typeclasses.models import (TypedObject, NickHandler)
from src.scripts.scripthandler import ScriptHandler from src.scripts.scripthandler import ScriptHandler
@ -100,7 +100,7 @@ class PlayerDB(TypedObject, AbstractUser):
db_is_bot = models.BooleanField(default=False, verbose_name="is_bot", help_text="Used to identify irc/imc2/rss bots") db_is_bot = models.BooleanField(default=False, verbose_name="is_bot", help_text="Used to identify irc/imc2/rss bots")
# Database manager # Database manager
objects = manager.PlayerManager() objects = PlayerDBManager()
# caches for quick lookups # caches for quick lookups
_typeclass_paths = settings.PLAYER_TYPECLASS_PATHS _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS

View file

@ -14,6 +14,7 @@ instead for most things).
import datetime import datetime
from django.conf import settings from django.conf import settings
from src.typeclasses.models import TypeclassBase from src.typeclasses.models import TypeclassBase
from src.players.manager import PlayerManager
from src.players.models import PlayerDB from src.players.models import PlayerDB
from src.comms.models import ChannelDB from src.comms.models import ChannelDB
from src.utils import logger from src.utils import logger
@ -28,6 +29,7 @@ class Player(PlayerDB):
Base typeclass for all Players. Base typeclass for all Players.
""" """
__metaclass__ = TypeclassBase __metaclass__ = TypeclassBase
objects = PlayerManager()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
""" """

View file

@ -3,7 +3,7 @@ The custom manager for Scripts.
""" """
from django.db.models import Q from django.db.models import Q
from src.typeclasses.managers import TypedObjectManager from src.typeclasses.managers import TypedObjectManager, TypeclassManager
from src.typeclasses.managers import returns_typeclass_list from src.typeclasses.managers import returns_typeclass_list
from src.utils.utils import make_iter from src.utils.utils import make_iter
__all__ = ("ScriptManager",) __all__ = ("ScriptManager",)
@ -12,7 +12,7 @@ _GA = object.__getattribute__
VALIDATE_ITERATION = 0 VALIDATE_ITERATION = 0
class ScriptManager(TypedObjectManager): class ScriptDBManager(TypedObjectManager):
""" """
This Scriptmanager implements methods for searching This Scriptmanager implements methods for searching
and manipulating Scripts directly from the database. and manipulating Scripts directly from the database.
@ -230,3 +230,6 @@ class ScriptManager(TypedObjectManager):
new_script = create.create_script(typeclass, key=new_key, obj=new_obj, new_script = create.create_script(typeclass, key=new_key, obj=new_obj,
locks=new_locks, autostart=True) locks=new_locks, autostart=True)
return new_script return new_script
class ScriptManager(ScriptDBManager, TypeclassManager):
pass

View file

@ -28,7 +28,7 @@ from django.conf import settings
from django.db import models from django.db import models
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from src.typeclasses.models import TypedObject from src.typeclasses.models import TypedObject
from src.scripts.manager import ScriptManager from src.scripts.manager import ScriptDBManager
from src.utils.utils import dbref, to_str from src.utils.utils import dbref, to_str
__all__ = ("ScriptDB",) __all__ = ("ScriptDB",)
@ -98,7 +98,7 @@ class ScriptDB(TypedObject):
db_is_active = models.BooleanField('script active', default=False) db_is_active = models.BooleanField('script active', default=False)
# Database manager # Database manager
objects = ScriptManager() objects = ScriptDBManager()
# caches for quick lookups # caches for quick lookups
_typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS _typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS

View file

@ -11,6 +11,7 @@ from django.conf import settings
from src.typeclasses.models import TypeclassBase from src.typeclasses.models import TypeclassBase
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from src.scripts.models import ScriptDB from src.scripts.models import ScriptDB
from src.scripts.manager import ScriptManager
from src.comms import channelhandler from src.comms import channelhandler
from src.utils import logger from src.utils import logger
@ -114,6 +115,7 @@ class ScriptBase(ScriptDB):
from the class 'Script' instead. from the class 'Script' instead.
""" """
__metaclass__ = TypeclassBase __metaclass__ = TypeclassBase
objects = ScriptManager()
def __eq__(self, other): def __eq__(self, other):
""" """

View file

@ -46,67 +46,6 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
# common methods for all typed managers. These are used # common methods for all typed managers. These are used
# in other methods. Returns querysets. # in other methods. Returns querysets.
def get(self, **kwargs):
"""
Overload the standard get. This will limit itself to only
return the current typeclass.
"""
kwargs.update({"db_typeclass_path":self.model.path})
return super(TypedObjectManager, self).get(**kwargs)
def filter(self, **kwargs):
"""
Overload of the standard filter function. This filter will
limit itself to only the current typeclass.
"""
kwargs.update({"db_typeclass_path":self.model.path})
return super(TypedObjectManager, self).filter(**kwargs)
def all(self, **kwargs):
"""
Overload method to return all matches, filtering for typeclass
"""
return super(TypedObjectManager, self).all(**kwargs).filter(db_typeclass_path=self.model.path)
def _get_subclasses(self, cls):
"""
Recursively get all subclasses to a class
"""
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.
"""
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(TypedObjectManager, self).get(**kwargs)
def filter_family(self, **kwargs):
"""
Variation of filter that allows results both from typeclass
and from subclasses of typeclass
"""
# 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(TypedObjectManager, self).filter(**kwargs)
def all_family(self, **kwargs):
"""
Return all matches, allowing matches from all subclasses of
the typeclass.
"""
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
for cls in self._get_subclasses(self.model)]
return super(TypedObjectManager, self).all(**kwargs).filter(db_typeclass_path__in=paths)
# Attribute manager methods # Attribute manager methods
def get_attribute(self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None): def get_attribute(self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None):
@ -337,3 +276,68 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
query = query | Q(db_typeclass_path__exact=parent.path) query = query | Q(db_typeclass_path__exact=parent.path)
# actually query the database # actually query the database
return self.filter(query) return self.filter(query)
class TypeclassManager(TypedObjectManager):
def get(self, **kwargs):
"""
Overload the standard get. This will limit itself to only
return the current typeclass.
"""
kwargs.update({"db_typeclass_path":self.model.path})
return super(TypedObjectManager, self).get(**kwargs)
def filter(self, **kwargs):
"""
Overload of the standard filter function. This filter will
limit itself to only the current typeclass.
"""
kwargs.update({"db_typeclass_path":self.model.path})
return super(TypedObjectManager, self).filter(**kwargs)
def all(self, **kwargs):
"""
Overload method to return all matches, filtering for typeclass
"""
return super(TypedObjectManager, self).all(**kwargs).filter(db_typeclass_path=self.model.path)
def _get_subclasses(self, cls):
"""
Recursively get all subclasses to a class
"""
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.
"""
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(TypedObjectManager, self).get(**kwargs)
def filter_family(self, **kwargs):
"""
Variation of filter that allows results both from typeclass
and from subclasses of typeclass
"""
# 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(TypedObjectManager, self).filter(**kwargs)
def all_family(self, **kwargs):
"""
Return all matches, allowing matches from all subclasses of
the typeclass.
"""
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
for cls in self._get_subclasses(self.model)]
return super(TypedObjectManager, self).all(**kwargs).filter(db_typeclass_path__in=paths)