1👍
The fact is that when you query a model (via a QuerySet method, or indirectly via a ForeignKey) you get non-polymorphic instances – in contrast to SQLAlchemy, where you get polymorphic instances.
This is because the fetched data corresponds only to the data you’re accessing (and it’s ancestors since they are known beforehand). By default, Django does not do any kind of select_related
to get the children, so you’re stuck with the base (i.e. current) class model of the foreign key or query set.
This means:
Vehicle.objects.get(pk=1).__class__ == Vehicle
will be always True, and:
Surprise.objects.get(pk=1).items.all()[0].__class__ == Vehicle
will be always True as well.
(assume for these examples that vehicle with pk=1 exists, surprise with pk=1 exists, and has at least one item)
There’s no clean solution for this EXCEPT by knowing your children classes. As you said: accessing variables like .car or .truck (considering classes Car and Truck exist) is the way. However if you hit the wrong children class (e.g. you hit vehicle.car
when vehicle
should be, actually, a Truck
instance) you will get an ObjectDoesNotExist
error. Disclaimer: Don’t know what would happen if you have two children classes with the same name in different modules.
If you want to have polymorphic behavior, which can abstract you from testing every possible subclass, an application exists (haven’t actually used it): https://django-polymorphic.readthedocs.org/en/latest/
0👍
According to Django Documentation:
If you have a Place that is also a Restaurant, you can get from the Place object to the Restaurant object by using the lower-case version of the model name:
p = Place.objects.get(id=12)
p.restaurant
Further to that:
However, if p in the above example was not a Restaurant (it had been created directly as a Place object or was the parent of some other class), referring to p.restaurant would raise a Restaurant.DoesNotExist exception.
So you answered the question on your own, you need to check the car attr, because that is what is pointing to the model you are looking for, if there is no car attr then the object was not created by the Car class.
- [Answer]-Wwwizer not working on Chrome
- [Answer]-502 Bad Gateway connecting Nginx to django via socket
- [Answer]-Pinax – Customizing the sign up process – get_profile()
0👍
As another workaround, I wrote this function that can be used for the same purpose without the need of django-polymorphic
:
def is_model_instance(object, model):
'''
`object` is expected to be a subclass of models.Model
`model` should be a string containing the name of a models.Model subclass
Return true if `object` has a reference to a `model` instance, false otherwise.
'''
model_name = model.lower()
if model_name in dir(object):
try:
statement = "object." + model_name
exec(statement)
return True
except object.DoesNotExist:
return False
else :
return False
Then I can easily do something like
>>> is_model_instance(Surprise.objects.get(pk=1).items.all()[0], Car)
True # this is indeed a Car
- [Answer]-Django templates variable issue
- [Answer]-Celery Flower Is Able To Shutdown Worker But Unable To Restart It
- [Answer]-Django login only using username and hash
- [Answer]-A simple for in statement causes an error