django one-to-many - django

Long story short: I have two models, and a database imported from XML. The model layout is as follows:
class A:
ForgeinKey(B)
class B:
list = {A1, A2 ... An}
Is there a replacement for {A1, A2 ... An} that would make B.list return a list of A's.
Edit: The idea is to have a field in B that lists all the A's that are pointing to it. I can't seem to figure out how to call A.objects.* from inside B's definition. I don't even know if that's possible.
Edit2: Solved, thanks everyone for help :)

If I understood correctly, you want B().list to return the result of SELECT * FROM A WHERE B_id = <B.id>?
You have to use related_name, then:
class A(Model):
b = ForeignKey(B, related_name='list')
Or, you can use the default name, "B().A_set"

Related

Django getting foreign-key object list

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

Django queryset exclude empty foreign key set

I have the following models where B has a many-to-one relationship with A:
class A(model.Model):
name = models.IntegerField()
class B(models.Model
a = models.ForeignKey(A, db_column='a_id')
When I use a queryset on A, is there a way to exclude the rows in A that have no rows in B?
Use isnull :
A.objects.filter(b__isnull=False).distinct()
Using distinct() prevents duplicate entries, otherwise each a appears once for every b which is linked to it.
no_rows_in_b = B.objects.all().select_related('a')
will get you all the B's with A's
Then you can cycle through them and output the A's
If you want non-repeats:
no_rows_in_b = B.objects.all().distinct('a').select_related('a')
Then:
for rec in no_rows_in_b:
print(rec.a)
Notice that if you want to be more explicit, you could do something like this:
A.objects.exclude(b__isnull=True).distinct()
using exclude instead of filter and using the True boolean arg.

How to use Q objects to check if any members of arbitrary-length list are in Many-To-Many Relationship

Suppose I have the following Django models:
class myObj1(models.Model):
myField1 = models.IntegerField()
class myObj2(models.Model):
myLocalObj1 = models.ManyToManyField(myObj1)
Furthermore, suppose I have a list of unique myObj1s:
a = myObj1(myField=1)
b = myObj1(myField=2)
c = myObj1(myField=3)
myTargetList = [a, b, c]
Now, I would like to write a Django query using Q objects such that it returns all the myObj2s that have any member of myTargetList as myLocalObj1. Furthermore, I don't know the exact size of myTargetList in advance.
How should I do it? This obviously won't work:
myObj2.objects.filter(Q(myLocalObj1__in=myTargetList))
EDIT: To make this a little more in line with what you are looking for (although I would not necessarily recommend doing things this way), you could:
vallist=[]
for b in myTargetList:
vallist.append(b.myField)
myObj2.objects.filter(myLocalObj1__in=myObj1.objects.filter(myField__in=vallist))
This is available in the Django docs here:
https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships

Django wrong behaviour on query relations

lately I found a weird behavior in Django. Then, I start thinking that what's wrong is the way I'm doing the work.
Lets assume that we have 2 models
class A(models.Model):
attr1 = models.CharField()
...
class B(models.Model):
a = models.ForeignKey("A",
related_name = "bs"
blank = True,
null = True)
So, if I have some items of B, without associations to A, say b1, b2, b3, when I set a new instance of A, say a1, if I query
a.bs.all()
b1, b2 and b3 are returned.
What's wrong with it? When I create a new instance, it should not rise any relation. I know that b1,b2 and b3 have no relations, but they can't be associated by default to any new instance.
Anyone know how to proceed in a Django way?
I know I can do the trick
if a1.id:
return []
else:
a1.bs.all()
But I think that's not the right way to do this.
Can anyone help me?
Thank you in advance
This is a bug in Django and is currently marked as "design decision needed":
https://code.djangoproject.com/ticket/14615

JPA2 Criteria Builder - Queries on abstract classes and multiple subclasses

first of all, sorry if this question has already been asked, but I couldn't find any similar questions nor answers for my problem.
My problem is, that I have several subclasses in several hierarchy levels inheriting from one subclass.
#Entity
public class A{ }
#Entity
public class B extends A { ... }
#Entity
public class C extends A{ ... }
#Entity
public class D extends C {
private String someAttribute;
}
#Entity
public class E extends C {
private String anotherAttribute;
}
I need to process a query on C and get all entities from C,D,E according to my criteria, which accesses attributes from D and E.
I noticed, that it is not possible to access for example someAttribute fro D executing a query on C. like this:
Root root = query.from(C.class);
Path p = root.get("someAttribute");
Path p2 = root.get("anotherAttribute");
Please note, that I cannot work with metamodels at this point.
In JPAQL I would code something like that:
`select e1 from C eq where someAttribute = .... or anotherAttribute = ....`
And it would resolve my hierarchy properly.
To solve the problem, I created my own annotation equivalent to #XmlSeeAlso and named it #PersistenceSeeAlso which tells me, which subclasses I have to look up to find my attribute. So when I process my hierarchy accoridng to #PersistenceSeeAlso and get my paths I need to create a new Root element for each subclass, that I look up for my attribute.
The main Problem here is, that query.form(clazz) creates a join on the query, which totally messes up my query, but I need a Root element on my type to resolve the path.
So my question is; is there a way, to handle multiple subclass selections with JPA2 CriteriaBuilder without creating new Root instances, maybe with EntityType?
Or am I doing something totally wrong?
Thank you very much in advance!
Best regards,
Q
sorry for the long wait!
That's a great question that I see all the time. The problem is that you are assuming information about the sub-types of C, which isn't exactly right.
If you use a "table per class" or "joined table" inheritance strategy, then the data for D and E are stored in separate tables and select e1 from C eq where someAttribute = .... or anotherAttribute = .... would not work, since those columns don't exist in C.
You would need to LEFT JOIN the columns from D and E onto C before you can filter. (I answered a similar question before that should help.