Hi everyone !
My think, i found some errors for manytomany field. Lets explain;
in models.py
class model1(models.Model):
field1 = models.CharField(max_length=100)
class model2(models.Model):
field2 = models.ManyToManyField(model1)
in views.py some code
...
field2 = [model1_obj1.id, model1_obj2.id]
model2.objects.get(field2__in = field2) #or
model2.objects.get_or_create(field2__in = field2)
...
when i try to use get() & get_or_create() i get some error:
MultipleObjectsReturned: get() returned more than one model2 – it returned 2!
but when i check to db i can see i have 1 model on database.
if i use the filter() method i dont get some error.
model2.objects.filter(field2__in = field2)
--> <QuerySet [<model2-object>]>
also when you hasnt got an object on db, if you try;
obj, create= model2.objects.get_or_create(field2__in = field2)
if create:
obj.field2.add(model1_obj1)
obj.field2.add(model1_obj2)
you can see object is created !
and create type is boolean → True
Finally i cant get the model object for manytomany field with some values. I think this is bug for source code. Am i wrong ? You can try it so sample !
Given how ManyToMany relationships work, there’s nothing you’ve posted here that seems like a bug to me.
Never lose sight of the fact that a ManyToManyField is not a field in either model. It’s an indication that there’s a “join table” containing two ForeignKey fields, one referencing each of the two related models.
If you think about these operations need to work in that context, the results that you are seeing make a lot of sense.
What you might want to do is either use the Django shell or log the actual queries being performed for these to get a better idea of what’s happening for each one.
For example your first get
query is going to execute something like this:
select model2.id from model2 inner join model2_model1 on (model2.id = model2_model1.id) where model2_model1.model1_id in (1, 2)
This is a query that will return two rows. (Try it! You’ll have to find the correct table names.)
My guess is that the filter
version only shows one row because of how those rows are converted into Python objects within the queryset. (I don’t know enough about the ORM internals to say for sure.)
Since a get
fails, that also explains why get_or_create
is showing a create
result.
When in doubt about results being received, always start with looking at the queries being used.
Actually my motivation is filter or get object. But filtered field is many to many field. Also i want to filter with specifical field value.
if i use Q libary, code will be this see;
from django.db.models import Q
model2.objects.filter( Q( field2 = model1_obj1) & Q(field2= model1_obj2 ) )
--> but this now working.
I solved my problem with using to double filter() method;
query = model2.objects.filter(field2 = model1_obj1).filter(field2 = model1_obj1)
Is django has a default function for manytomany filter ?
This is a different query than what you were trying to execute before.
Your original query:
is checking for field2 either being model1_obj1 or model1_obj2
Your second version here:
and here:
are an and
condition requiring that model2 be related to both obj1 and obj2.
These are two different logical conditions.
Of course I understand what you are saying. After reading the original documentation and what you wrote, I realized that I cannot do this with get() and get_or_create() .
but my answer is: Is django has a default function for manytomany specifical filter ?
and Why is the code below not working (returned empty query)?
(code updated for first version)
model2.objects.filter( Q( field2__in =[model1_obj1.id]) & Q(field2__in =[model1_obj2.id]) )
I’m sorry, I don’t understand what you’re asking for here.
Because you’re looking for rows where field2 is equal to both model1_obj1 and model1_obj2 at the same time.
Your expression could be logically simplified as:
Q( field2=model1_obj1) & Q(field2=model1_obj2)
which is never going to be true except for the case where model1_obj1 is a reference to the same object as model1_obj2.