'QuerySet' object has no attribute ERROR, trying to get related data on ManyToMany fields
Asked Answered
A

2

19

i have the following models:

class Tag(models.Model):
    tag_name = models.CharField(max_length=250)
    tagcat = models.ForeignKey('TagCat')

class Subject(models.Model):
    user = models.ManyToManyField(User)
    tags = models.ManyToManyField(Tag)

class TagCat(models.Model):
    cat_name = models.CharField(max_length=100)

So i have a subject, that has a tag. I want to loop the subjects and their appropriate tags, so I am trying to construct the right view. So far, I have:

def home(request):
    user1 = Subject.objects.filter(id=1)
    print(user1.tags.all())

I would expect to get the tags of the user through this print statement, but instead I get error

'QuerySet' object has no attribute 'tags'

How would I be getting the 'Subject' objects with their respective tags and pass them to template?

(Ideally all subjects. I did it with just one here, to simplify for the process of troubleshooting)

Arbitress answered 30/11, 2010 at 22:42 Comment(0)
U
34

filter returns a QuerySet (as you may have guessed), you want to do get instead

user1 = Subject.objects.get(id=1)

If the Subject does not exist you will get a Subject.DoesNotExist exception. There's also the get_object_or_404 shortcut in django.shortcuts that is useful if you're simply grabbing an object that is to be displayed in some way and you want to return a 404 if it is not available.

Unloosen answered 30/11, 2010 at 22:44 Comment(6)
Since I am a newbie, can I follow up on this with a short q?-> what exactly is the difference between get and filter? so to say they both get me the user, since I can print it's name. I am missing a major concept... if filter returns a queryset(not very clear what that is either) what does get return?Arbitress
But filter doesn't really get you the user, it gets you another QuerySet which describes some criteria to choose a set of Subject s from your set of objects (Subject.objects). Think of it as the difference between a table and a row within the table. QuerySets describe tables where the objects are the rows. In your case, your QuerySet is just a one-row table. get uniquely identifies an object out of the object set and returns that object instead of a single-row table.Unloosen
hm...More or less I get it. But get seems to retun only 1 item, since I get "'Subject' object is not iterable". This is the primary reason why I switched to filter, filter gave me something that I could loop. Now that I understand filter is wrong for the purposes, how do I get the 'get' to return many Subjects and their tags?Arbitress
If you want multiple things you use filter, and then you can iterate over that. for user in Subject.objects.filter([your filter criteria]): will give you a Subject object in that user variable for each iteration. That variable will have all the attributes you seek!Unloosen
Awesome! got it to work, it's wonderful! You're wonderful too.Arbitress
Though the logic is crooked, because essentially you are still doing a filter, and the fact that you are looping it and adding it to a list, doesn't seem to strike me where exactly the conversion from queryset to object is...Arbitress
S
3

QuerySet.get() will either return a single model as given by the criteria passed by it, or it will raise an exception.

Stanchion answered 30/11, 2010 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.