Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is model._meta.get_fields() returning unexpected relationship column names, and can this be prevented?

Imagine I have some models as below:

class User(AbstractUser):
    pass

class Medium(models.Model):
    researcher = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True, related_name="medium_researcher")
    old_medium_name = models.CharField(max_length=20, null=True, blank=True)

class Uptake(models.Model):
    material_quality = models.CharField(max_length=20, null=True, blank=True)
    medium = models.ForeignKey(Medium, on_delete=models.CASCADE, blank=True, null=True, related_name="uptake_medium")

Now I have a function to return all column names to generate some overview in my HTML as such:

from database.models import Medium
MODEL_HEADERS=[f.name for f in Medium._meta.get_fields()]
MODEL_HEADERS
['uptake_medium', 'id', 'researcher', 'old_medium_name']

Why does this return uptake_medium? As this is a ForeignKey relation set within the Uptake model, it should only be present within the Uptake model right? When I review the admin models this column does not show up, neither in the db.sqlite3 model when checking Uptake, so it seems to be sort of hidden, and only show up when requested with _meta. The relationship seems to be correct… This is causing a lot of problems with my code, and it would be great if only the ‘non-meta’ columns only could be returned. How should I approach?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Why does this return uptake_medium? As this is a ForeignKey relation set within the Uptake model, it should only be present within the Uptake model right?

You can access the relation in reverse, for example:

my_medium.uptake_medium.all()

to obtain all Updates related to the Medium instance named medium.

You can also filter on that field, for example:

Medium.objects.filter(uptake_medium__material_quantity=42)

hence it is accessible just like any field.

You can filter with:

from django.db.models.fields.reverse_related import ManyToOneRel

[f.name for f in Medium._meta.get_fields() if not isinstance(ManyToOneRel)]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading