Convert Django Model object to dict with all of the fields intact
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Converting a Django model instance to a dictionary is needed for JSON API responses, logging, testing, and data export. Django provides several built-in approaches: model_to_dict() from django.forms.models, the __dict__ attribute, and values() on QuerySets. Each has trade-offs regarding which fields are included (foreign keys, non-editable fields, many-to-many relations). This article covers all methods and their differences.
Using model_to_dict()
model_to_dict() returns a dictionary of all editable fields. By default, it excludes non-editable fields (like auto_now DateTimeFields) and includes foreign key IDs and many-to-many relations as lists of IDs.
Controlling Which Fields Are Included
Using dict
__dict__ includes all fields (including non-editable ones and the raw _id suffix for ForeignKey fields) but also includes Django's internal _state object. Filter keys starting with _ to clean it up.
Using values() on QuerySet
values() works at the database level, generating SQL that returns dictionaries instead of model instances. It is the most efficient method when you do not need the model object itself.
Custom to_dict Method
A custom to_dict() method gives full control over field inclusion, FK resolution, and serialization format.
Using Django REST Framework Serializers
DRF serializers handle nested objects, validation, and JSON-compatible output. Use them for API responses.
Comparison Table
| Method | Non-editable | FK as ID | FK resolved | M2M | JSON-safe |
| model_to_dict() | No | Yes | No | Yes | No |
| dict | Yes | Yes (_id) | No | No | No |
| values() | Yes | Yes (_id) | No | No | Partial |
| Custom to_dict() | You choose | You choose | Yes | Yes | Yes |
| DRF Serializer | You choose | You choose | Yes | Yes | Yes |
Common Pitfalls
- model_to_dict excludes non-editable fields: Fields with
editable=False(likeauto_nowandauto_now_add) are excluded bymodel_to_dict(). Use__dict__or a custom method to include them. - dict includes _state: The
_stateattribute is Django internal metadata. Always filter it out:{k: v for k, v in obj.__dict__.items() if not k.startswith('_')}. - ForeignKey fields use _id suffix in dict:
user.__dict__showsrole_id(the raw integer), notrole(the related object). Usemodel_to_dict()or accessuser.roledirectly for the related object. - Many-to-many fields missing:
__dict__andvalues()do not include M2M relationships. Usemodel_to_dict()(returns IDs) or a custom method (returns resolved values). - Non-serializable types in output: DateTime objects, Decimal, and UUID are not JSON-serializable. Use
DjangoJSONEncoderor convert them manually (.isoformat(),str()) beforejson.dumps().
Summary
model_to_dict(instance)is the quickest built-in but excludes non-editable fieldsinstance.__dict__includes all fields but requires filtering_stateand returns raw FK IDsQuerySet.values()is most efficient for bulk conversion directly from the database- Custom
to_dict()methods give full control over FK resolution, M2M, and serialization - DRF serializers are the standard choice for API responses with nested relationships

