darkhorse
darkhorse

Reputation: 8782

How to create a content tagging system for two models in Django?

Edited my question to make it more clear. And I am sorry if what i'm asking is obvious or easy to solve, I am just starting out.

Hello, I am developing a website which has 2 models for the content: Article and Comic. Now I want a system that allows me to tag Articles and Comics with certain keywords. These keywords can then be used to retrieve a list of objects from both the models and display them.

At first, I set up the system as follows:

class Article(models.Model):
    .....
class Comic(models.Model):
    .....
class Tag(models.Model):
    tag = models.CharField(max_length = 25)
    article = models.ForeignKey(Article)
    comic = models.ForeignKey(Comic)

However, this did not work out.

Then I tried implementing 2 different tag models for the 2 different models: ArticleTag and ComicTag, in the following way:

class Article(models.Model):
   .....
class ArticleTag(models.Model):
   tag = models.CharField(max_length = 25)
   article = models.ForeignKey(Article)

class Comic(models.Model):
    .....
class ComicTag(models.Model):
    tag = models.CharField(max_length = 25)
    comic = models.ForeignKey(Comic)

This also did not work, as I was able to get a list of tags of an article, but I could not get a list of articles that had the same tag. And also it was using 2 different tag models so that was also not preferable.

A user suggested a ManyToManyField based on the previous information I had provided. However, how would this exactly work?

Now, what is the best way to create a content tagging system using Django? It should preferably work with just 3 models: Article, Comic and Tag, not 4 like I tried. In conclusion, I want a system that lets me get a list of objects from 2 models using one single tag. So, I would really appreciate help of any kind as I am an amateur programming (pretty obvious) and I am completely stumped by this problem.

Upvotes: 1

Views: 919

Answers (1)

YPCrumble
YPCrumble

Reputation: 28722

You could use a ManyToManyField.

Basically something like the following. It's more intuitive if you change the name of ArticleTag.tag to ArticleTag.name. I've also added a related_name field to the M2M relationship so you can retrieve an article based on its tags using Article.objects.filter(tags__name="tag_name_here"). In the reverse direction, you could get all the tags for an article using ArticleTag.objects.filter(article__title="article_name_here").

class Article(models.Model):
    title = models.CharField(max_length=140)
    .....
class ArticleTag(models.Model):
    name = models.CharField(max_length = 25)
    articles = models.ManyToManyField(Article, related_name="tags")

[EDIT based on your updated question]

Based on your update, you could do this:

class Article(models.Model):
   .....

class Comic(models.Model):
    .....

class Tag(models.Model):
    tag = models.CharField(max_length = 25)
    articles = models.ManyToManyField(
        Article, 
        related_name="tags", 
        blank=True, 
        null=True
    )
    comics = models.ManyToManyField(
        Comic, 
        related_name="tags", 
        blank=True, 
        null=True
    )

This way an Article/Comic can have many different tags, and any one tag can tag many different articles/comics. The blank=True, null=True means that you don't have to have an associated comic/article with a given tag, i.e., one tag could happen tag only comics but no articles.

To get a list of articles with the same tag:

Article.objects.filter(tags__name="your_tag_name")

Upvotes: 1

Related Questions