How do I check if there are any ManyToMany field objects related to my model object?
For example, I have a model:
class Category(models.Model):
related_categories = models.ManyToManyField('self', blank=True)
I want to do something only if there are related objects existing:
if example_category.related_categories:
do_something()
I tried to do example_category.related_categories, example_category.related_categories.all(), example_category.related_categories.all().exists(), example_category.related_categories.count(), but none of these works for me.
I have no any additional conditions to filter by.
Is there any easy way to check emptiness of this field?
you should use the .exists method:
related_categories = example_category.related_categories
if related_categories.exists():
# do something
Related
I'm new to django. I'm using a ManyToMany field in my Profile model with Membership Model.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
picture = models.ImageField(blank=True)
membership = models.ManyToManyField(MemberShip, null=True)
What I want to do is I want to get all the users who has specific membership(from membership model)
For example I want the list of all the users who has the Red Membership. I researched and found out that select_related() or prefetch_related can help in some way. but I can't understand how can I use these methods to get what I want.
I've tried this:
user_memberships_all = Profile.objects.all()
for m in user_memberships_all:
affiliate_with_membership = m.membership.select_related('user').all()
but I get an error saying Invalid field name(s) given in select_related: 'user'.
if there is another of achieving this. can you please help with that. Thank You.
To get all Users related to a specific MemberShip you can follow the OneToOneField backwards and then filter on the ManyToManyField
# Filtering on a "name" attribute of MemberShip
User.objects.filter(profile__membership__name='red')
# Using a MemberShip instance
red_membership = MemberShip.objects.get(name='red')
User.objects.filter(profile__membership=red_membership)
i have two model classes and they are related by OneToOneField like here
class Book(models.Model):
is_user_ok = models.BooleanFiled()
class Mybook(models.Model):
book = models.OneToOneField( Book, related_name="Book", null=True, blank=True, on_delete=models.SET_NULL)
now i want make a queryset filter by book field property. but here book.is_user_ok
cannot be used. how can i make this queryset filter?
queryset = Mybook.objects.filter(book.is_user_ok=True)
You are looking a common problem, what you really want to do is related_name__column_name in filter, in your case you can try
queryset = Mybook.objects.filter(book__is_user_ok=True=True)
Reference from official docs:
https://docs.djangoproject.com/en/4.0/topics/db/queries/
double underscore is used for joins as you have already set the relationship in model variety of joins work here, it is used as per the model relation.
You are using a wrong syntax. Replace (book.is_user_ok=True) with (book__is_user_ok=True) The problem is, using '.' instead of '__'. Thats the correct syntax when dealing with another model class
I have this model:
class Person(models.Model):
something ...
employers = models.ManyToManyField('self', blank=True, related_name='employees')
When I do person.employees.all() I get this error: 'Person' object has no attribute 'employees'. Is the related name only created when there is an actual link in place. If yes, how can I check this?
EDIT: I'm aware of the hasattr() function. I'm still wondering why the attribute doesn't return an empty list when there's no related objects.
To use related_name with recursive many-to-many you need set symmetrical=False. Without it Django will not add employees attribute to the class. From the docs:
When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a person_set attribute to the Person class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.
So you can add symmetrical=False to the field:
employers = models.ManyToManyField('self', blank=True, related_name='employees', symmetrical=False)
person.employees.all() # will work now
or just use employers attribute:
person.employers.all()
I am building the example django polls application. I want to exclude all polls, which have no choices. For that I have to access the related choices objects:
return Question.objects.filter(
pub_date__lte=timezone.now()
).exclude(
choice_set__count=0
).order_by('-pub_date')[:5]
But this query results in a field error:
Cannot resolve keyword 'choice_set' into field. Choices are: choice, id, pub_date, question_text
How can I query related models from the query?
To filter against a related model, you just use the lower-case model name - you can see that choice is one of the available fields.
However, this still won't work; there is no __count attribute to filter against. You can add one by using annotations, but there is a simpler way: compare against None:
.exclude(choice=None)
In the Choice model set the related_name to the Question foreign key.
Example:
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices')
# other code..
And then your query should be something like that:
return (Question.objects
.filter(pub_date__lte=timezone.now(),
choices__isnull=False)
.order_by('-pub_date')[:5])
Note: There is no `__count' lookup. If you want to rely on counts then check the docs on this.
docs: https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_name
The _set only applies when you are using that to retrieve the related model outside of the queryset, instead, as the error suggests, you can just use choice
.exclude(choice__isnull=True)
Consider a simple ForeignKey relationship:
class ModelA(models.Model):
other_field = CharField()
class ModelB(models.Model):
my_field = CharField()
parent = ForeignKey(ModelA)
So I can do this:
my_fields = ModelB.objects.all().values('my_field')
Is there any way to reference other_field in the same call? I would assume something like this is possible:
all_fields = ModelB.objects.all().values('my_field', 'parent.other_field')
But apparently that's not the case. What's the easiest way to fetch the related field values?
If this means that the Django ORM needs to prefetch the related values resulting in a heavy query, so be it. I'm looking for the most elegant way to do this.
as per the docs you can use
...values('parent__other_field')