Search code examples
djangodjango-taggit

make case-insensitive tags with django-taggit


I added tags = TaggableManager(blank=True) to my models, but I want my tags to be case-insensitive. I saw some snippets of work arounds for this and wanted to ask if there is an easy way to do it? If I have to override some methods from the TaggableManager, please advise how can I do that?

Thanks in advance, Arshavski Alexander.


Solution

  • I have used this snippet for a similar issue. A copy of the code (reprinted for posterity):

    from django.db.models import Manager
    from django.db.models.query import QuerySet
    
    class CaseInsensitiveQuerySet(QuerySet):
        def _filter_or_exclude(self, mapper, *args, **kwargs):
            # 'name' is a field in your Model whose lookups you want case-insensitive by default
            if 'name' in kwargs:
                kwargs['name__iexact'] = kwargs['name']
                del kwargs['name']
            return super(CaseInsensitiveQuerySet, self)._filter_or_exclude(mapper, *args, **kwargs)
    
    # custom manager that overrides the initial query set
    class TagManager(Manager):
        def get_query_set(self):
            return CaseInsensitiveQuerySet(self.model)
    
    # and the model itself
    class Tag(models.Model):
        name = models.CharField(maxlength=50, unique=True, db_index=True)
    
        objects = TagManager()
    
        def __str__(self):
            return self.name
    # now...
    >>> tag = Tag(name='test')
    >>> tag.save()
    >>> Tag.objects.get(name='TEST')
    <Tag: test>
    

    Basically, you override the initial queryset so that all querysets take case insensitivity into account.