Evgeny
Evgeny

Reputation: 10896

How to introspect django model fields?

I am trying to obtain class information on a field inside a model, when I only know name of the field and name of the model (both plain strings). How is it possible?

I can load the model dynamically:

from django.db import models
model = models.get_model('myapp','mymodel')

Now I have field - 'myfield' - how can I get the class of that field?

If the field is relational - how to get related field?

Thanks a bunch!

Upvotes: 37

Views: 23425

Answers (4)

tobltobs
tobltobs

Reputation: 2929

The answer from Anurag Uniyal to use get_field_by_name is now (5 years later) outdated as get_field_by_name is deprecated. Django will give you the following hint:

RemovedInDjango110Warning: 'get_field_by_name is an unofficial API that has been deprecated. You may be able to replace it with 'get_field()'

API docs for get_field are here.

Upvotes: 10

Anurag Uniyal
Anurag Uniyal

Reputation: 88737

You can use model's _meta attribute to get field object and from field you can get relationship and much more e.g. consider a employee table which has a foreign key to a department table

In [1]: from django.db import models

In [2]: model = models.get_model('timeapp', 'Employee')

In [3]: dep_field = model._meta.get_field_by_name('department')

In [4]: dep_field[0].target_field
Out[4]: 'id'

In [5]: dep_field[0].related_model
Out[5]: <class 'timesite.timeapp.models.Department'>

from django/db/models/options.py

def get_field_by_name(self, name):
    """
    Returns the (field_object, model, direct, m2m), where field_object is
    the Field instance for the given name, model is the model containing
    this field (None for local fields), direct is True if the field exists
    on this model, and m2m is True for many-to-many relations. When
    'direct' is False, 'field_object' is the corresponding RelatedObject
    for this field (since the field doesn't have an instance associated
    with it).

    Uses a cache internally, so after the first access, this is very fast.
    """

Upvotes: 74

Gambitier
Gambitier

Reputation: 590

django.db.models.loading.get_model() has been removed in django 1.9. You are supposed to use django.apps instead.

'get_field_by_name is an unofficial API that has been deprecated in Django 1.10. You may be able to replace it with 'get_field()'

>>> from django.apps import apps
>>> from polls.models import Question
>>> QuestionModel = apps.get_model('polls','Question')
>>> QuestionModel._meta.get_field('pub_date')
>>> QuestionModel._meta.get_fields()
(<ManyToOneRel: polls.choice>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: question_text>, <django.db.models.fields.DateTimeField: pub_date>) 

link to issue

Upvotes: 1

user1847
user1847

Reputation: 3799

If you would like to see ALL fields on a Django model object you can simply introspect it by calling ._meta.get_fields() on the class (or an instantiated model object) to get at list of all fields. This API is current with the latest version of Django.

Example:

from django.contrib.auth.models import User
User._meta.get_fields()

This will return a tuple of all model fields. Documentation can be found HERE.

Upvotes: 4

Related Questions