django-taggit Documentation

repository·master·Indexed 25 days ago

https://github.com/jazzband/django-taggit

A library providing a simple way to add tagging functionality to Django models using TaggableManager. It includes features for managing tags via the Django admin, retrieving common tags with most_common(), finding similar objects with similar_objects(), and support for custom Tag models, custom through tables, and non-integer primary keys (UUIDs or CharFields).

Tokens
5.5K
Snippets
17
Records
30
Agent score
85%

What's inside django-taggit

  1. Explore external applications for django-taggit

    master

    Several third-party applications provide extended functionality for django-taggit. Note that these are unofficial and have not been reviewed or tested by the django-taggit maintainers.

    Available extensions include:

    • django-taggit-anywhere: A simpler approach to tagging with integration for django-taggit-helpers and django-taggit-labels.
    • django-taggit-helpers: Adds helper classes for Django admin pages: TaggitCounter, TaggitListFilter, TaggitStackedInline, and TaggitTabularInline.
    • django-taggit-labels: Provides a clickable label widget for the Django admin to select from managed tag sets.
    • django-taggit-serializer: Adds support for using taggit with django-rest-framework.
    • django-taggit-suggest: Provides support for defining keyword and regular expression rules for suggesting new tags (replaces the deprecated taggit.contrib.suggest).
    • django-taggit-templatetags: Exposes various taggit APIs directly to templates via templatetags, including tag clouds.
    • django-taggit-bulk: Adds an admin action for bulk tagging from the model admin instance list view.
  2. Use natural key support for Tag models

    master
    The Tag model in django-taggit supports Django's natural key serialization. This allows you to identify and serialize tags using human-readable identifiers (by default, the name field) instead of database IDs. This is useful for exporting and importing data via dumpdata and loaddata.
  3. Retrieve all tags using the Tag model

    master

    In a standard django-taggit setup, tags are stored in the Tag model located in taggit.models. You can retrieve all tags by querying this model directly.

    If you are using a custom model implementation (for example, if your models derive from a custom ItemBase), you should query your specific custom tag model instead.

  4. Save tags when using commit=False in ModelForms

    master

    If you save a ModelForm using commit=False, the tags (which are managed via a many-to-many relationship) will not be saved automatically. You must explicitly call form.save_m2m() after saving the instance to ensure the tags are persisted to the database.

    if request.method == "POST":
        form = MyFormClass(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.user = request.user
            obj.save()
            # Without this next line the tags won't be saved.
            form.save_m2m()
  5. Merge tags in the admin

    master

    The Taggit admin app supports merging multiple tags into a single new tag. Follow these steps:

    1. Navigate to the Tags page within the Taggit app in the Django admin.
    2. Select the checkboxes for the tags you wish to merge.
    3. Select Merge selected tags from the dropdown action list and click Go.
    4. On the following page, enter the name of the new tag you want to use as the replacement.
    5. Click Merge Tags.
    6. You will be redirected back to the tag list, and all instances of the selected tags will have been replaced by the new tag.
  6. Display tags in ModelAdmin list_display

    master

    You cannot include a TaggableManager directly in ModelAdmin.list_display because it will raise an AttributeError: '_TaggableManager' object has no attribute 'name' and cause performance issues due to excessive queries.

    To display tags in the list view, define a custom method on your ModelAdmin to format the tags as a string and override get_queryset to use prefetch_related('tags') to optimize database performance.

    class MyModelAdmin(admin.ModelAdmin):
        list_display = ['tag_list']
    
        def get_queryset(self, request):
            return super().get_queryset(request).prefetch_related('tags')
    
        def tag_list(self, obj):
            return u", ".join(o.name for o in obj.tags.all())
  7. Filter models by tags using Django ORM

    master

    You can use standard Django ORM filtering to find models associated with specific tags.

    • Filter by name: Use tags__name__in=[...].
    • Filter by slug: Use tags__slug__in=[...].
    • Custom Tag Models: If using a custom Tag model, you can filter on any fields present in that model.

    Note on Duplicates: When filtering by multiple tags, relational databases may return duplicate model instances. Use .distinct() on your QuerySet to ensure unique results.

    >>> # Filter by name
    >>> Food.objects.filter(tags__name__in=["delicious"])
    [<Food: apple>, <Food: pear>, <Food: plum>]
    
    >>> # Filter by multiple tags and avoid duplicates
    >>> Food.objects.filter(tags__name__in=["delicious", "red"]).distinct()
    [<Food: apple>]
  8. Use custom ForeignKeys instead of GenericForeignKeys

    master

    If you want to use a real ForeignKey instead of a GenericForeignKey (for better performance or referential integrity), create an intermediary model that subclasses taggit.models.TaggedItemBase. This model must include a field named content_object pointing to your model. Pass this model to the through argument of TaggableManager.

    Note: If you are using custom models, you must remove 'taggit' from your INSTALLED_APPS in settings.py to prevent the default models from being created.

    from django.db import models
    from taggit.managers import TaggableManager
    from taggit.models import TaggedItemBase
    
    
    class TaggedFood(TaggedItemBase):
        content_object = models.ForeignKey('Food', on_delete=models.CASCADE)
    
    class Food(models.Model):
        # ... fields here
    
        tags = TaggableManager(through=TaggedFood)
  9. Install and set up django-taggit

    master

    To use django-taggit, install the package via pip, add it to your Django INSTALLED_APPS, and run migrations.

    1. Install with pip: pip install django-taggit
    2. Add 'taggit' to your INSTALLED_APPS in your Django settings.
    3. Run ./manage.py migrate to create the necessary database tables.
    $ pip install django-taggit
  10. Use custom GenericForeignKeys for non-integer primary keys

    master

    The default GenericForeignKey assumes integer primary keys. If your model uses a non-integer primary key (like a CharField), your intermediary model must subclass taggit.models.CommonGenericTaggedItemBase and include an object_id field matching the type of your primary key.

    from django.db import models
    from taggit.managers import TaggableManager
    from taggit.models import CommonGenericTaggedItemBase, TaggedItemBase
    
    
    class GenericStringTaggedItem(CommonGenericTaggedItemBase, TaggedItemBase):
        object_id = models.CharField(max_length=50, verbose_name=_('Object id'), db_index=True)
    
    
    class Food(models.Model):
        food_id = models.CharField(primary_key=True)
        # ... fields here
    
        tags = TaggableManager(through=GenericStringTaggedItem)
  11. Use UUID primary keys with GenericUUIDTaggedItemBase

    master

    For models using UUID primary keys, use the taggit.models.GenericUUIDTaggedItemBase class. If you only inherit from GenericUUIDTaggedItemBase, you must manually define a tag field (a ForeignKey to your Tag model) in your intermediary class.

    from django.db import models
    from django.utils.translation import gettext_lazy as _
    import uuid
    from taggit.managers import TaggableManager
    from taggit.models import GenericUUIDTaggedItemBase, TaggedItemBase
    
    
    class UUIDTaggedItem(GenericUUIDTaggedItemBase, TaggedItemBase):
        # If you only inherit GenericUUIDTaggedItemBase, you need to define
        # a tag field. e.g.
        # tag = models.ForeignKey(Tag, related_name="uuid_tagged_items", on_delete=models.CASCADE)
    
        class Meta:
            verbose_name = _("Tag")
            verbose_name_plural = _("Tags")
    
    
    class Food(models.Model):
        id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
        # ... fields here
    
        tags = TaggableManager(through=UUIDTaggedItem)