BoostedAnimal
BoostedAnimal

Reputation: 150

How to have two tag fields i.e. two Taggable Managers in the same model?

I have a model for uploaded files and I now need to have two tag fields in that model. One for user tags and one for admin tags. I've tried several solutions but neither worked.

Here is my code now and it doesn't work. Not sure if this is to create two separate tables, one for user tags and for admin tags so any help would be appreciated. Also, if you could maybe explain to me what I'm doing because I'm lost.

class UserTags(CommonGenericTaggedItemBase, TaggedItemBase):
    object_id = models.CharField(max_length=50, db_index=True)
    objects = models.Manager()

class BaseTag(TagBase):
    pass


class AdminTags(CommonGenericTaggedItemBase, TaggableManager):
    object_id = models.CharField(max_length=50, db_index=True)
    tag = models.ForeignKey(BaseTag, on_delete=models.CASCADE)
    objects = models.Manager()


# Model for all uploaded files
class Uploaded(models.Model):
    objects: models.Manager()
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="users")
    time_uploaded = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=50)
    file = models.FileField(upload_to=MEDIA_ROOT)
    tag = TaggableManager(blank=True, through=UserTags, related_name='user_tags')
    tags = TaggableManager(blank=True, through=AdminTags, related_name='admin_tags')
    additional_description = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return f"{self.name} {self.file}"

Upvotes: 1

Views: 814

Answers (2)

Ryan
Ryan

Reputation: 24422

from taggit.managers import TaggableManager
from taggit.models import TaggedItemBase

class ThroughTagA(TaggedItemBase):
    content_object = models.ForeignKey('Post', on_delete=models.CASCADE)

class ThroughTagB(TaggedItemBase):
    content_object = models.ForeignKey('Post', on_delete=models.CASCADE)

class Post(models.Model):    
    # ...
    tags_a = TaggableManager(blank=True, through=ThroughTagA, related_name='tags_a')
    tags_b = TaggableManager(blank=True, through=ThroughTagB, related_name='tags_b')  

Adapted from https://github.com/jazzband/django-taggit/issues/50#issuecomment-4627355

Upvotes: 2

Yaro
Yaro

Reputation: 58

I would try to implement it like this.

from django.db import models
from taggit.managers import TaggableManager
from taggit.models import TaggedItemBase, ItemBase


class AdminTag(ItemBase):
    pass


class UserTag(ItemBase):
    pass


class ThroughAdminTag(TaggableManager):
    content_object = models.ForeignKey('AdminTag', on_delete=models.CASCADE)


class ThroughUserTag(TaggableManager):
    content_object = models.ForeignKey('UserTag', on_delete=models.CASCADE)


# Model for all uploaded files
class Uploaded(models.Model):
    objects = models.Manager()
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="users")
    time_uploaded = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=50)
    file = models.FileField(upload_to=MEDIA_ROOT)
    tag = TaggableManager(blank=True, through=ThroughUserTag, related_name='user_tags')
    tags = TaggableManager(blank=True, through=ThroughAdminTag, related_name='admin_tags')
    additional_description = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return f"{self.name} {self.file}"

Not sure whether AdminTag and UserTag need any fields. Inheriting them from ItemBase should, in theory, cover that.

Upvotes: 2

Related Questions