Find object in child class from parent class instance in django - django

Let's say I have a parent class (Products) and child class related by OneToOneField. Now let's say I have a Products instance object. How will I be able to access all the fields of child ?
class Products(models.Model):
......
class Child1(models.Model):
parent=models.OneToOneField(Products)
......
class Child2(models.Model):
parent=models.OneToOneField(Products)
......
Now let
product_instance=Products.objects.get(id=id)
How can I access child fields without knowing the child class name?

There is package called DeepCollector using this you can get all related objects
from deep_collector.core import DeepCollector
collector = DeepCollector()
collector.collect(Products)
related_objects = collector.get_collected_objects()
try this...

Related

Django Migration Modify Inherited Default

I have a model class in Django Parent with a subclass Child. Parent has a boolean field foo which defaults to True that Child inherited. I'd like to migrate my Child class so that
All new Child objects have a default of False for the foo field
All existing Child objects have the foo field set to False
How can I achieve this in Django?
Sometimes the simplest solutions are the best solutions.
You can override the foo field in your Child model:
models.py
class Parent(models.Model):
...
foo = models.BooleanField(default=True)
class Child(Parent):
...
foo = models.BooleanField(default=False)
For existing child instances, you can write a small script to update them. I usually create a view function and trigger it by visiting the associated url (but there are many ways to do this). Something like:
views.py
def update_children_foo_field(request):
for child in Child.models.objects.filter(foo=True):
child.foo = False
child.save()
return JsonResponse({'message' : 'Complete'})

Access related manager method from another manager

I am trying to access a manager method from a manager of a related model but I'm having no success.
Let's say these are my models:
class ModelA(models.Model):
description = models.TextField(blank=True)
objects = ModelAQuerySet.as_manager()
class ModelB (models.Model):
a = models.ForeignKey(ModelA, related_name='a_objs')
objects = ModelBQuerySet.as_manager()
And I am defining the managers as QuerySets, that is:
class ModelAQuerySet(models.QuerySet):
def description_starts_with(self, desc):
return self.filter(description__startswith=desc)
class ModelBQuerySet(models.QuerySet):
pass
What I would to do is to create a ModelBQuerySet method that prefetch modelA objects starting with a certain description.
Here's a WRONG example of what I am trying to do:
class ModelBQuerySet(models.QuerySet):
def prefetch_a_objs_starts_with(self, desc):
return self.prefetch_related(
Prefetch('a_objs',
queryset=ModelAQuerySet.description_starts_with(desc),
to_attr='a_objs_with_desc'))
This of course doesn't work because description_starts_with is an instance method, and here I am invoking it from the class.
Even this is completely wrong I hope it gets the idea of what I'm trying to do.
Question is: how to create a models.QuerySet method with a prefetch that can access its related models.QuerySet instance methods?

Overwrite parent model attribute from child model

I have the following model parent
class ModelParent(PolymorphicModel):
company = models.CharField(max_length=50)
.......
and the model child
class ModelChild(ModelParent)
company = models.CharField(max_length=10, blank=True)
...........
how can I make the model child company attribute overwrite the parent company model attribute without making the abstract parent model
This is not possible without an abstract parent model, unfortunately.
Field name “hiding” is not permitted
In normal Python class inheritance, it is permissible for a child class to override any attribute from the parent class. In Django, this isn’t usually permitted for model fields. If a non-abstract model base class has a field called author, you can’t create another model field or define an attribute called author in any class that inherits from that base class.
This restriction doesn’t apply to model fields inherited from an abstract model. Such fields may be overridden with another field or value, or be removed by setting field_name = None.
A recommendation instead would be to simply create a property or rename the child model's field. Another thing you could do is remove the parent model's "company" field and move it to all of the children models instead.
class ModelChild(ModelParent)
child_company = models.CharField(max_length=10, blank=True)
...........

(django) get query of child class

I have a super class like this:
class Superclass(models.Model):
number = models.PositiveIntegerField()
class Meta:
abstract = True
def get_next(self):
return Superclass.objects.get(number=self.number+1)
Now, I have a child class that inherits from the superclass.
What's the problem?
I can't do this: Superclass.objects because the superclass doesn't refer to any database table.
I don't want to query all Superclass childs, only the one of the current child class, like this: When I do instance_of_child1.get_next I don't want to get an instance of Child2.
How to solve this?
My first idea was to add a static constant to any child class that contains the class (So I could do self.myclass.objects) But this seems to be not a good way.
Make the method get_next being part of the child class. Problem: there will be duplicates.
This should work:
def get_next(self):
return self.__class__.objects.get(number=self.number+1)

Find all instances of child models matching query

I have base class Publication, which Book and Magazine inherit from.
class Author(models.Model):
pass
class Publication(models.Model):
author = models.ForeignKey(Author)
class Book(Publication):
pass
class Magazine(Publication):
pass
I want to find all Book and Magazine objects with a certain author. Since the foreign key to Author is on the parent class Publication, my attempts at a query all return Publication objects rather than the child classes:
# Both of these return Publication objects, not Book/Magazine objects
Author.objects.get(pk=1).publication_set
Publication.objects.get(author_pk=1)
Is there a way to get all instances of child classes with a certain author, without manually running the query for all child classes like Book.objects.get(author_pk=1) (in reality I have more than two child classes)?
You might need to use an external package to get this kind of functionality. This looks like what you need: https://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager
Specifically:
from model_utils.managers import InheritanceManager
class Place(models.Model):
# ...
objects = InheritanceManager()
class Restaurant(Place):
# ...
class Bar(Place):
# ...
nearby_places = Place.objects.filter(location='here').select_subclasses()
for place in nearby_places:
# "place" will automatically be an instance of Place, Restaurant, or Bar