mark base model as abstract
[matthijs/upstream/django-ldapdb.git] / ldapdb / models / base.py
index 41d00e8c684b3fa7483973a5478b888808cce290..ddf21a2aebff8e66230db55ec8d08ccaa0f6b679 100644 (file)
@@ -1,78 +1,76 @@
 # -*- coding: utf-8 -*-
 # 
 # django-ldapdb
 # -*- coding: utf-8 -*-
 # 
 # django-ldapdb
-# Copyright (C) 2009-2010 BollorĂ© telecom
+# Copyright (c) 2009-2010, BollorĂ© telecom
+# All rights reserved.
+# 
 # See AUTHORS file for a full list of contributors.
 # 
 # See AUTHORS file for a full list of contributors.
 # 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+# 
+#     1. Redistributions of source code must retain the above copyright notice, 
+#        this list of conditions and the following disclaimer.
+#     
+#     2. Redistributions in binary form must reproduce the above copyright 
+#        notice, this list of conditions and the following disclaimer in the
+#        documentation and/or other materials provided with the distribution.
 # 
 # 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
+#     3. Neither the name of BollorĂ© telecom nor the names of its contributors
+#        may be used to endorse or promote products derived from this software
+#        without specific prior written permission.
 # 
 # 
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 
 import ldap
 import logging
 
 import django.db.models
 #
 
 import ldap
 import logging
 
 import django.db.models
+from django.db import connections, router
 from django.db.models import signals
 
 import ldapdb
 from django.db.models import signals
 
 import ldapdb
-from ldapdb.models.query import QuerySet
-
-class ModelBase(django.db.models.base.ModelBase):
-    """
-    Metaclass for all LDAP models.
-    """
-    def __new__(cls, name, bases, attrs):
-        super_new = super(ModelBase, cls).__new__
-        new_class = super_new(cls, name, bases, attrs)
-
-        # patch manager to use our own QuerySet class
-        if not new_class._meta.abstract:
-            def get_query_set():
-                return QuerySet(new_class)
-            new_class.objects.get_query_set = get_query_set
-            new_class._default_manager.get_query_set = get_query_set
-
-        return new_class
 
 class Model(django.db.models.base.Model):
     """
     Base class for all LDAP models.
     """
 
 class Model(django.db.models.base.Model):
     """
     Base class for all LDAP models.
     """
-    __metaclass__ = ModelBase
-
     dn = django.db.models.fields.CharField(max_length=200)
 
     # meta-data
     base_dn = None
     dn = django.db.models.fields.CharField(max_length=200)
 
     # meta-data
     base_dn = None
+    search_scope = ldap.SCOPE_SUBTREE
     object_classes = ['top']
 
     def __init__(self, *args, **kwargs):
         super(Model, self).__init__(*args, **kwargs)
         self.saved_pk = self.pk
 
     object_classes = ['top']
 
     def __init__(self, *args, **kwargs):
         super(Model, self).__init__(*args, **kwargs)
         self.saved_pk = self.pk
 
-    def _collect_sub_objects(self, collector):
+    def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
         """
         This private API seems to be called by the admin interface in django 1.2
         """
         """
         This private API seems to be called by the admin interface in django 1.2
         """
-        pass
+        pk_val = self._get_pk_val()
+        seen_objs.add(self.__class__, pk_val, self,
+                      type(parent), parent, nullable)
 
     def build_rdn(self):
         """
         Build the Relative Distinguished Name for this entry.
         """
         bits = []
 
     def build_rdn(self):
         """
         Build the Relative Distinguished Name for this entry.
         """
         bits = []
-        for field in self._meta.local_fields:
-            if field.primary_key:
+        for field in self._meta.fields:
+            if field.db_column and field.primary_key:
                 bits.append("%s=%s" % (field.db_column, getattr(self, field.name)))
         if not len(bits):
             raise Exception("Could not build Distinguished Name")
                 bits.append("%s=%s" % (field.db_column, getattr(self, field.name)))
         if not len(bits):
             raise Exception("Could not build Distinguished Name")
@@ -85,30 +83,37 @@ class Model(django.db.models.base.Model):
         return "%s,%s" % (self.build_rdn(), self.base_dn)
         raise Exception("Could not build Distinguished Name")
 
         return "%s,%s" % (self.build_rdn(), self.base_dn)
         raise Exception("Could not build Distinguished Name")
 
-    def delete(self):
+    def delete(self, using=None):
         """
         Delete this entry.
         """
         """
         Delete this entry.
         """
+        using = using or router.db_for_write(self.__class__, instance=self)
+        connection = connections[using]
         logging.debug("Deleting LDAP entry %s" % self.dn)
         logging.debug("Deleting LDAP entry %s" % self.dn)
-        ldapdb.connection.delete_s(self.dn)
+        connection.delete_s(self.dn)
         signals.post_delete.send(sender=self.__class__, instance=self)
         signals.post_delete.send(sender=self.__class__, instance=self)
-        
-    def save(self):
+
+    def save(self, using=None):
+        """
+        Saves the current instance.
+        """
+        using = using or router.db_for_write(self.__class__, instance=self)
+        connection = connections[using]
         if not self.dn:
             # create a new entry
             record_exists = False 
             entry = [('objectClass', self.object_classes)]
             new_dn = self.build_dn()
 
         if not self.dn:
             # create a new entry
             record_exists = False 
             entry = [('objectClass', self.object_classes)]
             new_dn = self.build_dn()
 
-            for field in self._meta.local_fields:
+            for field in self._meta.fields:
                 if not field.db_column:
                     continue
                 value = getattr(self, field.name)
                 if value:
                 if not field.db_column:
                     continue
                 value = getattr(self, field.name)
                 if value:
-                    entry.append((field.db_column, field.get_db_prep_save(value, connection=ldapdb.connection)))
+                    entry.append((field.db_column, field.get_db_prep_save(value, connection=connection)))
 
             logging.debug("Creating new LDAP entry %s" % new_dn)
 
             logging.debug("Creating new LDAP entry %s" % new_dn)
-            ldapdb.connection.add_s(new_dn, entry)
+            connection.add_s(new_dn, entry)
 
             # update object
             self.dn = new_dn
 
             # update object
             self.dn = new_dn
@@ -118,14 +123,14 @@ class Model(django.db.models.base.Model):
             record_exists = True
             modlist = []
             orig = self.__class__.objects.get(pk=self.saved_pk)
             record_exists = True
             modlist = []
             orig = self.__class__.objects.get(pk=self.saved_pk)
-            for field in self._meta.local_fields:
+            for field in self._meta.fields:
                 if not field.db_column:
                     continue
                 old_value = getattr(orig, field.name, None)
                 new_value = getattr(self, field.name, None)
                 if old_value != new_value:
                     if new_value:
                 if not field.db_column:
                     continue
                 old_value = getattr(orig, field.name, None)
                 new_value = getattr(self, field.name, None)
                 if old_value != new_value:
                     if new_value:
-                        modlist.append((ldap.MOD_REPLACE, field.db_column, field.get_db_prep_save(new_value, connection=ldapdb.connection)))
+                        modlist.append((ldap.MOD_REPLACE, field.db_column, field.get_db_prep_save(new_value, connection=connection)))
                     elif old_value:
                         modlist.append((ldap.MOD_DELETE, field.db_column, None))
 
                     elif old_value:
                         modlist.append((ldap.MOD_DELETE, field.db_column, None))
 
@@ -134,11 +139,11 @@ class Model(django.db.models.base.Model):
                 new_dn = self.build_dn()
                 if new_dn != self.dn:
                     logging.debug("Renaming LDAP entry %s to %s" % (self.dn, new_dn))
                 new_dn = self.build_dn()
                 if new_dn != self.dn:
                     logging.debug("Renaming LDAP entry %s to %s" % (self.dn, new_dn))
-                    ldapdb.connection.rename_s(self.dn, self.build_rdn())
+                    connection.rename_s(self.dn, self.build_rdn())
                     self.dn = new_dn
             
                 logging.debug("Modifying existing LDAP entry %s" % self.dn)
                     self.dn = new_dn
             
                 logging.debug("Modifying existing LDAP entry %s" % self.dn)
-                ldapdb.connection.modify_s(self.dn, modlist)
+                connection.modify_s(self.dn, modlist)
             else:
                 logging.debug("No changes to be saved to LDAP entry %s" % self.dn)
 
             else:
                 logging.debug("No changes to be saved to LDAP entry %s" % self.dn)
 
@@ -158,3 +163,5 @@ class Model(django.db.models.base.Model):
         new_class = new.classobj(name, (base_class,), {'base_dn': base_dn, '__module__': base_class.__module__})
         return new_class
 
         new_class = new.classobj(name, (base_class,), {'base_dn': base_dn, '__module__': base_class.__module__})
         return new_class
 
+    class Meta:
+        abstract = True