Filtering inherited objects - django

I have a base class A . Two derived classes B , C.
Now I have a global class witch contains a many-to-many relation to object A.
Class D:
aObjects : ManyToMany("A")
how could know the real object the filter query return in object D.
I mean : d.objects.get(id=5)
now d has n objects of class A, but they are a mix of A,B or C.
How can get only those of type B in the query.
Thanks in advance.

There's no way to do this automatically. The documentation is quite clear that there's no way to tell from an instance of a base class whether or not it should 'actually' be an instance of a derived class.
The only thing to do is to define a field on the base class that shows what derived type it is, and set this automatically in the the save() method of the various derived classes. Then you can filter on the value of this field.

Will this works for you
filter(lambda x: isinstance(x, B), d.objects.get(id=5))

Related

Best way to implement models with many overlapping fields in Django?

I need to implement the following logic: there is a big model Base with many fields and several smaller models sharing some field subsets with it and with each other. For example, let's say that Base has fields a, b, c, d, e and f; model A has fields a, b, g; model B has fields b, c, d, g; model C has fields d, e, f, g.
Trying to do proper inheritance from abstract models will very quickly lead to a mess, but making manual copies of fields also seems suboptimal, since every field from the main model is present in the smaller ones and so will have to be listed twice. What's a good way to approach this?
You need to inherit from Base and make it to be abstract .
And then override fields that you don't need with None.
Django documentation mentions this here .
Fields inherited from abstract base classes can be overridden with another field or value, or be removed with None.

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 one-to-many

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"

Why do you have to set both id and pk to None to copy a Django model with inheritance?

The Django docs recommend copying a model instance thus:
original.pk = None
original.save()
But if you "use inheritance" -- apparently meaning if the model's class is a subclass of a subclass of models.Model -- you need to do it slightly differently.
Specifically, the doc says:
Due to how inheritance works, you have to set both pk and id to None:
and gives an example analogous to this:
original.pk = None
original.id = None
original.save()
This seems kludgey. In any case, I'd like to understand what's going on. Why does using inheritance require you to set the id field to None also? Don't all Django models inherit from models.Model in any case?
(NOTE: I'm omitting the bit from the doc about copying m2m fields, which incidentally seems even more kludgey.)
It's because MTI (Multiple Table Inheritance), the type you're talking about here, stores the object across multiple tables. Take this example:
class Animal(models.Model):
...
class Dog(Animal):
...
When you create a Dog, all the fields on Animal are saved into the table for Animal, and just the fields directly on Dog are saved to the table for Dog. When you lookup the Dog later, Django queries both tables and stitches them together.
Both tables, however need primary keys, and Django uses AutoFields for that, which are simply positive integer fields. So Dog has an id and Animal has an id. The pk is filled with the id for the Animal part because this is the main piece, and Dog's id doesn't matter. However, if you're going to make a copy, you need to copy both pieces. Otherwise, the Animal part will of the copy will not get it's own Dog part of the copy.

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.