63

If you came here from Google looking for model to dict, skip my question, and just jump down to the first answer. My question will only confuse you.

Is there a good way in Django to entire set of a Model's objects into a single dictionary? I mean, like this:

class DictModel(models.Model):
    key = models.CharField(20)
    value = models.CharField(200)


DictModel.objects.all().to_dict()

... with the result being a dictionary with the key/value pairs made up of records in the Model? Has anyone else seen this as being useful for them?

Thanks.

Update
I just wanted to add is that my ultimate goal is to be able to do a simple variable lookup inside a Template. Something like:

{{ DictModel.exampleKey }}

With a result of DictModel.objects.get(key__exact=exampleKey).value

Overall, though, you guys have really surprised me with how helpful allof your responses are, and how different the ways to approach it can be. Thanks a lot.

Update October 2011: This question is the top result if you Google "django model_to_dict", which is actually pretty awful given that it solves a different problem than what I was asking.

What I wanted was to be able to map all of the instances in a queryset into a single dictionary with a specified model field as the key.
model_to_dict, on the other hand converts a single model instance into a dictionary.

Now, my needs at the time were pretty darn specific, and probably extremely rare (I can't even remember the project I needed it for, or why). So I would be pretty surprised that anyone looking for information about model_to_dict is going to find my question actually useful. Sorry.

model_to_dict seems to be a much more common usage case than I had.

Update Dec 2011:
I changed the title to hopefully better reflect my original intent.

LarrikJ
  • 904
  • 1
  • 8
  • 11
  • 1
    If you are looking for how to convert a single django model to a dictionary, please go here: http://stackoverflow.com/q/21925671/2800876 – Zags Oct 18 '16 at 20:34
  • 1
    `list_of_json = [model_to_dict(model) for model in list_of_models]` – FreshPow Sep 21 '17 at 20:58
  • [This](https://stackoverflow.com/a/1123354/11875147) is the only answer which **fully answers the OP's exact question**. – Jakub Holan Jun 03 '23 at 20:59

12 Answers12

217

You can also rely on django code already written ;).

from django.forms.models import model_to_dict
model_to_dict(instance, fields=[], exclude=[])
Arthur Debert
  • 10,237
  • 5
  • 26
  • 21
  • 12
    It is very nice solution but I've noticed that there is a catch. Since this method was written for usage in forms it doesn't dump fields that have editable=False flag. – Lukasz Korzybski Oct 20 '10 at 10:23
  • 1
    It might be added that this doesn't seem to get the fields of a parent model. – Izz ad-Din Ruhulessin Nov 02 '10 at 10:04
  • 37
    `model_to_dict(instance, fields=[field.name for field in instance._meta.fields])` – Filip Dupanović Dec 20 '10 at 16:39
  • 6
    Given how highly rated this answer is, I feel the need to point out that model_to_dict offers something fundamentally different than what I was originally asking for. model_to_dict turns a single model instance into a dictionary, which is great. What I wanted was to be able to map all of the instances in a queryset into a single dictionary with a specified model field as the key. – LarrikJ Oct 27 '11 at 19:21
  • 9
    @LarrikJ From your question, I can't deduce that that is what you wanted at all. Moreover, using `model_to_dict` allows you to achieve exactly what you said your end goal was. And let's not forget, the title of your question is "Converting an entire Model into a single dictionary" – Herman Schaaf Nov 04 '11 at 14:56
  • 4
    `model_to_dict(instance, fields=[field.name for field in instance._meta.fields])` will NOT dump fields that have `editable=False` flag. Use this instead: `{field.name: field.value_from_object(instance) for field in instance._meta.fields}` – Rockallite Jul 08 '14 at 14:13
26

You are looking for the Values member of QuerySet which allows you to get a list of dictionaries from your query

Returns a ValuesQuerySet -- a QuerySet that evaluates to a list of dictionaries instead of model-instance objects. Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects.

>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]
Tom Leys
  • 18,473
  • 7
  • 40
  • 62
19

Does this need to create an actual dict? could you get by with only something that looked like a dict?

class DictModelAdaptor():
    def __init__(self, model):
        self.model = model

    def __getitem__(self, key):
        return self.model.objects.get(key=key)

    def __setitem__(self, key, item):
        pair = self.model()
        pair.key = key
        pair.value = item
        pair.save()

    def __contains__(self, key):
        ...

You could then wrap a model in this way:

modelDict = DictModelAdaptor(DictModel)
modelDict["name"] = "Bob Jones"

etc...

SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • If this works in Template variable lookups, this may actually be what I want. Have you tried this? It'll be a few hours before I can. – LarrikJ Jul 14 '09 at 15:20
  • Yes, I have used container adapters in many situations, although I have certainly not wanted to use a whole model in this way. Also please note that this example is somewhat abbreviated. You will want to add some additional handlers and proper error handling. – SingleNegationElimination Jul 14 '09 at 23:03
  • I picked this answer because it fits my specific situation the best (which is slightly more complicated a situation than I described). The other responses were great, and worked fine as well. My favorite part was that lookups are done one at a time, instead of loading the whole table at once. I didn't even realize I wanted that until I saw it. – LarrikJ Jul 16 '09 at 14:32
17

You want the in_bulk queryset method which, according to the docs:

Takes a list of field values (id_list) and the field_name for those values, and returns a dictionary mapping each value to an instance of the object with the given field value. If id_list isn’t provided, all objects in the queryset are returned. field_name must be a unique field, and it defaults to the primary key.

It takes a list of IDs, so you'll need to get that first via the values_list method:

ids = MyModel.objects.values_list('id', flat=True)
ids_to_model_instances = MyModel.objects.in_bulk(ids)
# {1: <MyModel: 1>, 2: <MyModel: 2>, 3: <MyModel: 3>}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
14

You can use the python serializer:

from django.core import serializers
data = serializers.serialize('python', DictModel.objects.all())
Luper Rouch
  • 9,304
  • 7
  • 42
  • 56
  • I haven't tried Django's serializers yet, so I'm having trouble figuring out how this would work. I think I'll need to try this idea in an interactive session. It seems like it could be a solution, though. Thanks. – LarrikJ Jul 14 '09 at 15:29
  • 1
    django `serializers` can do serializations to `queryset`, while `model_to_dict` can only serialize to model instance. – yegle Apr 26 '12 at 07:12
8

use

dict(((m.key, m.value) for m in DictModel.objects.all())

As suggested by Tom Leys, we do not need to get whole object, we can get only those values we need e.g.

dict(((m['key'], m['value']) for m in DictModel.objects.values('key', 'value')))

and if you need all values, it is better to keep whole object in dict e.g.

dict(((m.key, m) for m in DictModel.objects.all())
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • 1
    We should combine solutions - dict(((m['key'], m['value']) for m in DictModel.objects.all().values()) - this way the hidden id field isn't returned from the DB. – Tom Leys Jul 14 '09 at 03:50
  • ILY, your answer is the **only answer which answers the OP's exact question** (and also my question). – Jakub Holan Jun 03 '23 at 21:01
6

dict((x.name, getattr(o, x.name)) for x in o._meta.fields)

tug
  • 201
  • 2
  • 3
  • One of differences between this and Luper's solution with serialize('python', ...) is that here foreign key fields will be represented as actual related objects. Using serialize you will get only id value of related object, not the object itself. – Lukasz Korzybski Oct 20 '10 at 12:52
4

Perhaps I'm missing something, but Django objects have a __dict__ attribute which seems be what you want.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
bjw
  • 2,046
  • 18
  • 33
2

To get values of a models into dictionary, add below code at the place where u need that dictionary

from models import DictModel

activity_map = dict(Plan.objects.values_list('key', 'value'))

activity_map is a dictionary which contains required information .

kleopatra
  • 51,061
  • 28
  • 99
  • 211
eswar
  • 41
  • 1
2
user = mymodel.objects.all()
user.values() 

You can also try

user.values_list() # getting as list
Rajan Mandanka
  • 2,003
  • 21
  • 13
1

To get a map of all of the instances in a queryset into a single dictionary with a specified model field as the key, try doing this

from django.forms.models import model_to_dict
from myApp.models import myModel

allObjs = myModel.objects.all()
f = {}         # initialise the output
key = 'key'    # one of the fields from myModel

[f.update({x[key]: x}) for x in [model_to_dict(y) for y in allObjs]]
return f
iancoleman
  • 2,766
  • 2
  • 19
  • 17
1

Or were you trying to do something like:

def someview(req):
    models = MyModel.objects.all()
    toTuple = lambda field: (getattr(field, 'someatt'), getattr(field, 'someotheratt'))  
    data = dict(map(toTuple,models))
    return render_to_response(template, data)