table of contents only for custom PDF (for now)
[wolnelektury.git] / src / newtagging / models.py
index 694f5b8..b90ea8e 100644 (file)
@@ -3,19 +3,16 @@
 Models and managers for generic tagging.
 """
 
 Models and managers for generic tagging.
 """
 
-from django.contrib.contenttypes.fields import GenericForeignKey
 from django.contrib.contenttypes.models import ContentType
 from django.db import connection, models
 from django.contrib.contenttypes.models import ContentType
 from django.db import connection, models
-from django.utils.translation import ugettext_lazy as _
 from django.db.models.base import ModelBase
 from django.db.models.base import ModelBase
-from django.core.exceptions import ObjectDoesNotExist
 from django.dispatch import Signal
 
 qn = connection.ops.quote_name
 
 from django.dispatch import Signal
 
 qn = connection.ops.quote_name
 
-
 tags_updated = Signal(providing_args=["affected_tags"])
 
 tags_updated = Signal(providing_args=["affected_tags"])
 
+
 def get_queryset_and_model(queryset_or_model):
     """
     Given a ``QuerySet`` or a ``Model``, returns a two-tuple of
 def get_queryset_and_model(queryset_or_model):
     """
     Given a ``QuerySet`` or a ``Model``, returns a two-tuple of
@@ -27,7 +24,7 @@ def get_queryset_and_model(queryset_or_model):
     try:
         return queryset_or_model, queryset_or_model.model
     except AttributeError:
     try:
         return queryset_or_model, queryset_or_model.model
     except AttributeError:
-        return queryset_or_model._default_manager.all(), queryset_or_model
+        return queryset_or_model.objects.all(), queryset_or_model
 
 
 ############
 
 
 ############
@@ -58,18 +55,19 @@ class TagManager(models.Manager):
         updated_tags = self.model.get_tag_list(tags)
 
         # Remove tags which no longer apply
         updated_tags = self.model.get_tag_list(tags)
 
         # Remove tags which no longer apply
-        tags_for_removal = [tag for tag in current_tags \
-                            if tag not in updated_tags]
+        tags_for_removal = [tag for tag in current_tags if tag not in updated_tags]
         if len(tags_for_removal):
         if len(tags_for_removal):
-            self.intermediary_table_model._default_manager.filter(content_type__pk=content_type.pk,
-                                               object_id=obj.pk,
-                                               tag__in=tags_for_removal).delete()
+            self.intermediary_table_model.objects.filter(
+                content_type__pk=content_type.pk,
+                object_id=obj.pk,
+                tag__in=tags_for_removal).delete()
         # Add new tags
         # Add new tags
-        tags_to_add = [tag for tag in updated_tags
-                       if tag not in current_tags]
+        tags_to_add = [tag for tag in updated_tags if tag not in current_tags]
         for tag in tags_to_add:
         for tag in tags_to_add:
-            if tag not in current_tags:
-                self.intermediary_table_model._default_manager.create(tag=tag, content_object=obj)
+            existing = self.intermediary_table_model.objects.filter(
+                content_type__pk=content_type.pk, object_id=obj.pk, tag=tag)
+            if not existing:
+                self.intermediary_table_model.objects.create(tag=tag, content_object=obj)
 
         tags_updated.send(sender=type(obj), instance=obj, affected_tags=tags_to_add + tags_for_removal)
 
 
         tags_updated.send(sender=type(obj), instance=obj, affected_tags=tags_to_add + tags_for_removal)
 
@@ -78,8 +76,18 @@ class TagManager(models.Manager):
         Remove tag from an object.
         """
         content_type = ContentType.objects.get_for_model(obj)
         Remove tag from an object.
         """
         content_type = ContentType.objects.get_for_model(obj)
-        self.intermediary_table_model._default_manager.filter(content_type__pk=content_type.pk,
-            object_id=obj.pk, tag=tag).delete()
+        self.intermediary_table_model.objects.filter(
+            content_type__pk=content_type.pk, object_id=obj.pk, tag=tag).delete()
+
+    def add_tag(self, obj, tag):
+        """
+        Add tag to an object.
+        """
+        content_type = ContentType.objects.get_for_model(obj)
+        relations = self.intermediary_table_model.objects.filter(
+            content_type__pk=content_type.pk, object_id=obj.pk, tag=tag)
+        if not relations:
+            self.intermediary_table_model.objects.create(tag=tag, content_object=obj)
 
     def get_for_object(self, obj):
         """
 
     def get_for_object(self, obj):
         """
@@ -105,9 +113,10 @@ class TagManager(models.Manager):
         ``filters`` argument.
         """
         # TODO: Do we really need this filters stuff?
         ``filters`` argument.
         """
         # TODO: Do we really need this filters stuff?
-        if filters is None: filters = {}
+        if filters is None:
+            filters = {}
 
 
-        queryset = model._default_manager.filter()
+        queryset = model.objects.filter()
         for f in filters.items():
             queryset.query.add_filter(f)
         usage = self.usage_for_queryset(queryset, counts)
         for f in filters.items():
             queryset.query.add_filter(f)
         usage = self.usage_for_queryset(queryset, counts)
@@ -122,10 +131,9 @@ class TagManager(models.Manager):
         each tag, indicating how many times it has been used against
         the Model class in question.
         """
         each tag, indicating how many times it has been used against
         the Model class in question.
         """
-        usage = self.model._default_manager.filter(
+        usage = self.model.objects.filter(
             items__content_type=ContentType.objects.get_for_model(queryset.model),
             items__content_type=ContentType.objects.get_for_model(queryset.model),
-            items__object_id__in=queryset
-            )
+            items__object_id__in=queryset)
         if counts:
             usage = usage.annotate(count=models.Count('id'))
         else:
         if counts:
             usage = usage.annotate(count=models.Count('id'))
         else:
@@ -197,42 +205,13 @@ class TaggedItemManager(models.Manager):
 ##########
 # Models #
 ##########
 ##########
 # Models #
 ##########
-def create_intermediary_table_model(model):
-    """Create an intermediary table model for the specific tag model"""
-    name = model.__name__ + 'Relation'
-
-    class Meta:
-        db_table = '%s_relation' % model._meta.db_table
-        unique_together = (('tag', 'content_type', 'object_id'),)
-        app_label = model._meta.app_label
-
-    def obj_unicode(self):
-        try:
-            return u'%s [%s]' % (self.content_type.get_object_for_this_type(pk=self.object_id), self.tag)
-        except ObjectDoesNotExist:
-            return u'<deleted> [%s]' % self.tag
-
-    # Set up a dictionary to simulate declarations within a class
-    attrs = {
-        '__module__': model.__module__,
-        'Meta': Meta,
-        'tag': models.ForeignKey(model, verbose_name=_('tag'), related_name='items'),
-        'content_type': models.ForeignKey(ContentType, verbose_name=_('content type')),
-        'object_id': models.PositiveIntegerField(_('object id'), db_index=True),
-        'content_object': GenericForeignKey('content_type', 'object_id'),
-        '__unicode__': obj_unicode,
-    }
-
-    return type(name, (models.Model,), attrs)
-
 
 class TagMeta(ModelBase):
 
 class TagMeta(ModelBase):
-    "Metaclass for tag models (models inheriting from TagBase)."
+    """Metaclass for tag models (models inheriting from TagBase)."""
     def __new__(mcs, name, bases, attrs):
         model = super(TagMeta, mcs).__new__(mcs, name, bases, attrs)
         if not model._meta.abstract:
     def __new__(mcs, name, bases, attrs):
         model = super(TagMeta, mcs).__new__(mcs, name, bases, attrs)
         if not model._meta.abstract:
-            # Create an intermediary table and register custom managers for concrete models
-            model.intermediary_table_model = create_intermediary_table_model(model)
+            # Register custom managers for concrete models
             TagManager(model.intermediary_table_model).contribute_to_class(model, 'objects')
             TaggedItemManager(model).contribute_to_class(model.intermediary_table_model, 'objects')
         return model
             TagManager(model.intermediary_table_model).contribute_to_class(model, 'objects')
             TaggedItemManager(model).contribute_to_class(model.intermediary_table_model, 'objects')
         return model
@@ -256,4 +235,3 @@ class TagBase(models.Model):
             return [tag_list]
         else:
             return tag_list
             return [tag_list]
         else:
             return tag_list
-