Commit c32c2ce3 by Alex Gaynor

Fix all the remaining bugs

parent 515106b7
......@@ -8,7 +8,7 @@ from django.db.models.query_utils import QueryWrapper
from django.utils.translation import ugettext_lazy as _
from taggit.forms import TagField
from taggit.models import Tag, TaggedItem
from taggit.models import Tag, TaggedItem, GenericTaggedItemBase
from taggit.utils import require_instance_manager
......@@ -39,7 +39,7 @@ class TaggableRel(ManyToManyRel):
class TaggableManager(object):
def __init__(self, verbose_name=_("Tags"), through=None):
self.use_gfk = through is None
self.use_gfk = through is None or issubclass(through, GenericTaggedItemBase)
self.through = through or TaggedItem
self.rel = TaggableRel(to=self.through._meta.get_field("tag").rel.to)
self.verbose_name = verbose_name
......@@ -134,7 +134,7 @@ class _TaggableManager(models.Manager):
def add(self, *tags):
for tag in tags:
if not isinstance(tag, Tag):
tag, _ = Tag.objects.get_or_create(name=tag)
tag, _ = self.through.tag_model().objects.get_or_create(name=tag)
self.through.objects.get_or_create(tag=tag, **self._lookup_kwargs())
@require_instance_manager
......
......@@ -62,6 +62,10 @@ class ItemBase(models.Model):
abstract = True
@classmethod
def tag_model(cls):
return cls._meta.get_field_by_name("tag")[0].rel.to
@classmethod
def tag_relname(cls):
return cls._meta.get_field_by_name('tag')[0].rel.related_name
......@@ -110,7 +114,7 @@ class GenericTaggedItemBase(ItemBase):
class Meta:
abstract=True
@classmethod
def lookup_kwargs(cls, instance):
return {
......@@ -121,14 +125,12 @@ class GenericTaggedItemBase(ItemBase):
@classmethod
def tags_for(cls, model, instance=None):
ct = ContentType.objects.get_for_model(model)
kwargs = {
"%s__content_type" % cls.tag_relname(): ct
}
if instance is not None:
return Tag.objects.filter(**{
'%s__object_id' % cls.tag_relname(): instance.pk,
'%s__content_type' % cls.tag_relname(): ct
})
return Tag.objects.filter(**{
'%s__content_type' % cls.tag_relname(): ct
}).distinct()
kwargs["%s__object_id" % cls.tag_relname()] = instance.pk
return cls.tag_model().objects.filter(**kwargs).distinct()
class TaggedItem(GenericTaggedItemBase, TaggedItemBase):
......
from django import forms
from taggit.tests.models import Food, DirectFood, CustomPKFood
from taggit.tests.models import Food, DirectFood, CustomPKFood, OfficialFood
class FoodForm(forms.ModelForm):
......@@ -14,3 +14,7 @@ class DirectFoodForm(forms.ModelForm):
class CustomPKFoodForm(forms.ModelForm):
class Meta:
model = CustomPKFood
class OfficialFoodForm(forms.ModelForm):
class Meta:
model = OfficialFood
......@@ -85,7 +85,7 @@ class OfficialThroughModel(GenericTaggedItemBase):
tag = models.ForeignKey(OfficialTag, related_name="tagged_items")
class OfficialFood(models.Model):
name = models.CharField(max_length=50, primary_key=True)
name = models.CharField(max_length=50)
tags = TaggableManager(through=OfficialThroughModel)
......@@ -93,13 +93,13 @@ class OfficialFood(models.Model):
return self.name
class OfficialPet(models.Model):
name = models.CharField(max_length=50, primary_key=True)
name = models.CharField(max_length=50)
tags = TaggableManager(through=OfficialThroughModel)
def __unicode__(self):
return self.name
class OfficialHousePet(CustomPKPet):
class OfficialHousePet(OfficialPet):
trained = models.BooleanField()
......@@ -3,11 +3,12 @@ from unittest import TestCase as UnitTestCase
from django.test import TestCase, TransactionTestCase
from taggit.models import Tag, TaggedItem
from taggit.tests.forms import FoodForm, DirectFoodForm, CustomPKFoodForm
from taggit.tests.forms import (FoodForm, DirectFoodForm, CustomPKFoodForm,
OfficialFoodForm)
from taggit.tests.models import (Food, Pet, HousePet, DirectFood, DirectPet,
DirectHousePet, TaggedPet, CustomPKFood, CustomPKPet, CustomPKHousePet,
TaggedCustomPKPet, OfficialFood, OfficialPet, OfficialHousePet,
OfficialThroughModel)
OfficialThroughModel, OfficialTag)
from taggit.utils import parse_tags, edit_string_for_tags
......@@ -45,6 +46,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
pet_model = Pet
housepet_model = HousePet
taggeditem_model = TaggedItem
tag_model = Tag
def test_add_tag(self):
apple = self.food_model.objects.create(name="apple")
......@@ -73,7 +75,7 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
apple.tags.remove('green')
self.assert_tags_equal(apple.tags.all(), ['red'])
self.assert_tags_equal(self.food_model.tags.all(), ['green', 'red'])
tag = Tag.objects.create(name="delicious")
tag = self.tag_model.objects.create(name="delicious")
apple.tags.add(tag)
self.assert_tags_equal(apple.tags.all(), ["red", "delicious"])
......@@ -128,12 +130,12 @@ class TaggableManagerTestCase(BaseTaggingTestCase):
[apple]
)
tag = Tag.objects.get(name="woof")
tag = self.tag_model.objects.get(name="woof")
self.assertEqual(list(self.pet_model.objects.filter(tags__name__in=[tag])), [dog])
cat = self.housepet_model.objects.create(name="cat", trained=True)
cat.tags.add("fuzzy")
self.assertEqual(
map(lambda o: o.pk, self.pet_model.objects.filter(tags__name__in=["fuzzy"])),
[kitty.pk, cat.pk]
......@@ -219,6 +221,7 @@ class TaggableManagerOfficialTestCase(TaggableManagerTestCase):
pet_model = OfficialPet
housepet_model = OfficialHousePet
taggeditem_model = OfficialThroughModel
tag_model = OfficialTag
class TaggableFormTestCase(BaseTaggingTestCase):
......@@ -260,6 +263,10 @@ class TaggableFormCustomPKTestCase(TaggableFormTestCase):
form_class = CustomPKFoodForm
food_model = CustomPKFood
class TaggableFormOfficialTestCase(TaggableFormTestCase):
form_class = OfficialFoodForm
food_model = OfficialFood
class TagStringParseTestCase(UnitTestCase):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment