I have two tables A and B. A.bs is a ManyToManyField onto B.
I want to fetch all a in A where a.bs contains a certain b from B.
The only way I know how to do it is like this:
def get_all_A_containing_b(b):
return filter(lambda a: b in a.bs, A.objects.all())
I'd prefer to have this all done by the DBMS, but I don't want to write any SQL code or use django internals.
The SQL would look something like this: (I can't remember the semantics of JOIN and nulls so this may be wrong)
SELECT * FROM A a
LEFT JOIN A2B a2b on a2b.a_id = a.id
LEFT JOIN B b on a2b.b_id = b.id
WHERE b.id = $b;
where $b is replaced with the id of the b from B I want.
whats the problem with
as = A.objects.filter(bs=b)?
Have you tried using the reverse lookup through one of the automatic _set attributes?
b = B.objects.get( b_id)
a_list = b.a_set.all()
I am answering from my mobile so I can't test if this works.
-Justin
Related
I need to build a query using Django ORM, that looks like this one in SQL:
select * from A where id not in (select a_id from B where ... )
I try to use such code:
ids = B.objects.filter(...)
a_objects = A.object.exclude(id__in=Subquery(ids.values('a__id'))).all()
The problem is that instead of nested select Django generates query that looks like
select * from A where id not in (1, 2, 3, 4, 5 ....)
where in clause explicitly lists all ids that should be excluded, making result sql unreadable when it is printed into logs. Is it possible to adjst this query, so nested select is used?
So I see that your goal is to get all the A's that have no foreign key relations from B's. If I'm right, then you can just use inverse lookup to do it.
So, when you define models like that:
class A:
pass
class B:
a = ForeignKey(to=a, related_name='bs')
You can filter it like this:
A.objects.filter(bs__isnull=True)
Also, if you don't define related_name, it will default to b_set, so you will be able to A.objects.filter(b_set__isnull=True)
to make a filter on B you can
ids = B.objects.filter(x=x).values_list('id',flat=true)
you get a list of ids then make
a_objects = A.object.exclude(id__in=ids)
as mentioned before if there is a relation
You don't need to do anything special, just use the queryset directly in your filter.
ids = B.objects.filter(...)
a_objects = A.object.exclude(id__in=ids).all()
# that should generate the subquery statement
select * from A where NOT (id in (select a_id from B where ... ))
I have model like this:
class A:
....
class B:
....
a = model.ForeignKey(A, related_name='a')
....
Let's assume there is an B object.
I can get A object like this:
b = B()
a = b.a
Then what is the simplest way to get all B object related with A?
Additionally,
I can get a list of A.
list_a = A.objects.filter()
Then what is the simplest way of getting a list of B which relates with A object in the list_a?
One more reverse case: I have a list of B:
list_b = B.objects.filter()
Then what is the simplest and optimized way to get the list of A object related to the B object in the list_b?
B.objects.filter(a__in=a_list)
note that you can filter on related objects like this (instead if executing two queries do it in one)
for example if your a_list is a query like this:
a_list = A.objects.filter(field=2)
you can filter B like this:
B.objects.filter(a__field=2)
which is more readable and also django can optimize it too)
Update: you can query reversed relations the same way
A.objects.filter(b__in=b_list)
A.objects.filter(b__field=2)
note that it's better to change your code to
a = model.ForeignKey(A, related_name='b')
b is the name of the field in reveres relations so an_a_instance.b.all() returns all instances of b which are pointing at given a_instance
Let's Assume I have a parent and a child tables which are implemented via inheritance in django.
models.py
class A(models.Model)
a = CharField()
class B(A):
b = CharField()
Now I want to select column b from table B I execute:
B.objects.only('b').get(id=4)
But this statement queries database 2 times:
SELECT `b`.`a_ptr_id`, `b`.`b` FROM `b` WHERE `b`.`a_ptr_id` = 4; args=(4,)
SELECT `a`.`a`, `b`.`a_id` FROM `b` INNER JOIN `a` ON (`b`.`a_ptr_id` = `b`.`id`) WHERE `b`.`a_ptr_id` = 4; args=(4,)
How do I generate SINGLE query like select b from b where a_ptr_id = ? using django models?
I want to query database one single time!
It turns out that only 1 query was generated. The 2nd query was caused because I checked all of this in debug mode. My IDE evaluated the object automatically which led to querying the database with
SELECT `a`.`a`, `b`.`a_id` FROM `b` INNER JOIN `a` ON (`b`.`a_ptr_id` = `b`.`id`) WHERE `b`.`a_ptr_id` = 4;
In views.py
I want to randomly choose one record with my filter:
a=Entry.objects.filter(first_name__contains='Br')).order_by('?')[0]
b=a.id
c=Entry.objects.filter(first_name__contains='Br')).order_by('?')[0]
d=c.id
It is possible that b and d are same.
But my goal is to get each time different entry object and id. How can I do this?
How about fetching both objects in the same query? That way you know you have two distinct entries.
a, c = Entry.objects.filter(first_name__contains='Br')).order_by('?')[0:2]
b = a.id
d = c.id
Note that this will raise a ValueError if the filter matches fewer than two entries.
assume I have two objects article and comment. What I would like to do is to fetch all comments, which article.id is IN (1,2,3,4). What is the best way to achieve it ? Am I forced to use JOIN? Right now I have something like this;
dql = "SELECT c FROM Comment c LEFT OUTER JOIN c.article a WHERE a.id IN :articles ORDER BY a.id ASC";
$query = $this->entityManager->createQuery($dql);
$query->setParameter("articles", array(1,2,3,4));
I haven't tested this query but I believe something like this should work, but it would be lovely to write something like c.article IN articles (without JOIN)
This does work, AFAIK:
SELECT c FROM Comment c WHERE c.article IN(:articles)
$query->setParameter('articles', array(1,2,3,4));