jeremy_lord
jeremy_lord

Reputation: 469

Iterate over ManyToMany field Django

I am having some problems with iterating over a ManyToMany field. I want to have a Post and Tag model, and have the Post model extend the Tag model in the form of a ManyToMany relation.

Below are both my Tag and Post models.

class Tag(models.Model):
    name = models.CharField(max_length=100)

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

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=150)
    content = RichTextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(unique=True,default="",max_length=1000)
    tag = models.ManyToManyField(Tag,related_name='tags',blank=True)

    # .... other non related functions

However, when I am in the Django shell, I can't seem to loop over these tags, despite the object having tags associated to it.

For example, I would do post1 = Post.objects.all()[0], and then post1.tag.name.all(), however it would give me an error saying "AttributeError: 'NoneType' object has no attribute 'all'

Everything else I have tried failed. What can I fix to solve the issue?

Thank you in advance

Upvotes: 2

Views: 3023

Answers (2)

Muhammad Zeshan Arif
Muhammad Zeshan Arif

Reputation: 475

It is very simple to iterate over ManyToManyField

for tag in post1.tag.all():
   print(tag.name)

Other than iteration, I have some other suggestions. Like tag will have many tags so naming it tags is more suitable. Secondly related_name is The name to use for the relation from the related object back to this one So in your case it should be posts instead of tags

So it will look like

tags = models.ManyToManyField(Tag, related_name='posts', blank=True)

Now you can access posts from any specific tag using this related_name. For example, If you have tag

tag1 = Tag.objects.all()[0]

Now you can get all posts with this tag using following line

tag1_posts = tag1.posts.all()

Upvotes: 0

nishant
nishant

Reputation: 2606

You are suppose to iterate through tags object like this

for tag in post1.tag.all():
   print(tag.name)

Upvotes: 5

Related Questions