Skip to content
Advertisement

Convert Django Model object to dict with all of the fields intact

How does one convert a django Model object to a dict with all of its fields? All ideally includes foreign keys and fields with editable=False.

Let me elaborate. Let’s say I have a django model like the following:

JavaScript

In the terminal, I have done the following:

JavaScript

I want to convert this to the following dictionary:

JavaScript

Questions with unsatisfactory answers:

Django: Converting an entire set of a Model’s objects into a single dictionary

How can I turn Django Model objects into a dictionary and still have their foreign keys?

Advertisement

Answer

There are many ways to convert an instance to a dictionary, with varying degrees of corner case handling and closeness to the desired result.


1. instance.__dict__

JavaScript

which returns

JavaScript

This is by far the simplest, but is missing many_to_many, foreign_key is misnamed, and it has two unwanted extra things in it.


2. model_to_dict

JavaScript

which returns

JavaScript

This is the only one with many_to_many, but is missing the uneditable fields.


3. model_to_dict(..., fields=...)

JavaScript

which returns

JavaScript

This is strictly worse than the standard model_to_dict invocation.


4. query_set.values()

JavaScript

which returns

JavaScript

This is the same output as instance.__dict__ but without the extra fields. foreign_key_id is still wrong and many_to_many is still missing.


5. Custom Function

The code for django’s model_to_dict had most of the answer. It explicitly removed non-editable fields, so removing that check and getting the ids of foreign keys for many to many fields results in the following code which behaves as desired:

JavaScript

While this is the most complicated option, calling to_dict(instance) gives us exactly the desired result:

JavaScript

6. Use Serializers

Django Rest Framework‘s ModelSerializer allows you to build a serializer automatically from a model.

JavaScript

returns

JavaScript

This is almost as good as the custom function, but auto_now_add is a string instead of a datetime object.


Bonus Round: better model printing

If you want a django model that has a better python command-line display, have your models child-class the following:

JavaScript

So, for example, if we define our models as such:

JavaScript

Calling SomeModel.objects.first() now gives output like this:

JavaScript
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement