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
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?
For Django versions 1.8 and later:
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
[f.name 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
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
This does the trick. I only test it in Django 1.7.
your_fields = YourModel._meta.local_fields your_field_names = [f.name for f in your_fields]
Model._meta.local_fields does not contain many-to-many fields. You should get them using
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 list(set(chain.from_iterable( (field.name, field.attname) if hasattr(field, 'attname') else (field.name,) 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) )))
Just to add, I am using self object, this worked for me:
[f.name for f in self.model._meta.get_fields()]
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. 'auth.User.id'
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 field:field.name, Parent._model._meta.get_fields()) ['id', 'child']
while, as shown by @Rockallite
>>> map(lambda field:field.name, Parent._model._meta.local_fields) ['id']
def __iter__(self): field_names = [f.name 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