Django: Get list of model fields?

mpen Source

I've defined a User class which (ultimately) inherits from models.Model. I want to get a list of all the fields defined for this model. For example, phone_number = CharField(max_length=20). Basically, I want to retrieve anything that inherits from the Field class.

I thought I'd be able to retrieve these by taking advantage of inspect.getmembers(model), but the list it returns doesn't contain any of these fields. It looks like Django has already gotten a hold of the class and added all its magic attributes and stripped out what's actually been defined. So... how can I get these fields? They probably have a function for retrieving them for their own internal purposes?



answered 8 years ago rossipedia #1

For Django versions 1.8 and later:

The get_all_field_names() method is deprecated starting from Django 1.8 and will be removed in 1.10.

The documentation page linked above provides a fully backwards-compatible implementation of get_all_field_names(), but for most purposes [ for f in MyModel._meta.get_fields()] should work just fine.

For Django versions before 1.8:


That should do the trick.

That requires an actual model instance. If all you have is a subclass of django.db.models.Model, then you should call myproject.myapp.models.MyModel._meta.get_all_field_names()

answered 6 years ago bjw #2

I find adding this to django models quite helpful:

def __iter__(self):
    for field_name in self._meta.get_all_field_names():
        value = getattr(self, field_name, None)
        yield (field_name, value)

This lets you do:

for field, val in object:
    print field, val

answered 4 years ago Rockallite #3

This does the trick. I only test it in Django 1.7.

your_fields = YourModel._meta.local_fields
your_field_names = [ for f in your_fields]

Model._meta.local_fields does not contain many-to-many fields. You should get them using Model._meta.local_many_to_many.

answered 3 years ago Wil #4

The get_all_related_fields() method mentioned herein has been deprecated in 1.8. From now on it's get_fields().

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

answered 2 years ago aboutaaron #5

MyModel._meta.get_all_field_names() was deprecated several versions back and removed in Django 1.10.

Here's the backwards-compatible suggestion from the docs:

from itertools import chain

    (, field.attname) if hasattr(field, 'attname') else (,)
    for field in MyModel._meta.get_fields()
    # For complete backwards compatibility, you may want to exclude
    # GenericForeignKey from the results.
    if not (field.many_to_one and field.related_model is None)

answered 2 years ago arrt_ #6

Just to add, I am using self object, this worked for me:

[ for f in self.model._meta.get_fields()]

answered 11 months ago Nader Alexan #7

It is not clear whether you have an instance of the class or the class itself and trying to retrieve the fields, but either way, consider the following code

Using an instance

instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields

Using a class

User._meta.__dict__.get("fields") # returns the fields

# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
    field.__str__() # e.g. ''

answered 9 months ago Kanak #8

At least with Django 1.9.9 -- the version I'm currently using --, note that .get_fields() actually also "considers" any foreign model as a field, which may be problematic. Say you have:

class Parent(models.Model):
    id = UUIDField(primary_key=True)

class Child(models.Model):
    parent = models.ForeignKey(Parent)

It follows that

>>> map(lambda, Parent._model._meta.get_fields())
['id', 'child']

while, as shown by @Rockallite

>>> map(lambda, Parent._model._meta.local_fields)

answered 9 months ago Vivek Anand #9

def __iter__(self):
    field_names = [ for f in self._meta.fields]
    for field_name in field_names:
        value = getattr(self, field_name, None)
        yield (field_name, value)

This worked for me in django==1.11.8

answered 2 months ago Adam Pawluczuk #10

Why not just use that: inspectdb

Example output:

class GuardianUserobjectpermission(models.Model):
    id = models.IntegerField(primary_key=True)  # AutoField?
    object_pk = models.CharField(max_length=255)
    content_type = models.ForeignKey(DjangoContentType, models.DO_NOTHING)
    permission = models.ForeignKey(AuthPermission, models.DO_NOTHING)
    user = models.ForeignKey(CustomUsers, models.DO_NOTHING)

    class Meta:
        managed = False
        db_table = 'guardian_userobjectpermission'
        unique_together = (('user', 'permission', 'object_pk'),)

comments powered by Disqus