Search code examples
pythondjangodjango-related-manager

How do I find the class that RelatedManager is managing when the QuerySet is empty?


I have two models that are related. From the object of one, I want to get the class name of the other. Currently, I'm doing it this way:

    associated_model = getattr(object_specific, associated_model_str)
    associated_model_instance = associated_model.all().first()
    if associated_model_instance:
        associated_model_name = associated_model_instance.__class__.__name__

In this case, object_specific is an object of a model. associated_model_str is the name of the attribute in that model that has a reference to the second model. When I get the attribute into associated_model, this variable contain the RelatedManager for the second model. If I do .all().first() I will get an object from that model, from where I can get the class name by checking the attribute .__class__.__name__. The problem is that sometimes I don't have any instances of the second model in the database associated to the instance of the first model. In other words, the .all() comes empty. So I don't have an instance of the second class to get the class name. How can I get that class name directly from the RelatedManager?


Solution

  • Assuming the following models, you should be able to just access the "model" field of the class.

    
    class ModelA(models.Model):
       name = models.TextField('name')
    
    
    class ModelB(models.Model):
       name = models.TextField('name')
       model_a = models.ForeignKey(ModelA, on_delete=models.PROTECT, related_name='model_bs')
    
    
    

    Then in the view or whereever

    ma = ModelA.objects.first()
    
    ma.model_bs.model.__name__
    
    

    You can see in the django code

    https://github.com/django/django/blob/ca9872905559026af82000e46cde6f7dedc897b6/django/db/models/fields/related_descriptors.py#L559

    It sets a property of the class called "model" which it then assigns the related model as a Class, which gives you access to name