How do I convert a Django QuerySet into list of dicts?
Use the .values()
method:
>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]
Note: the result is a QuerySet
which mostly behaves like a list, but isn't actually an instance of list
. Use list(Blog.objects.values(…))
if you really need an instance of list
.
get dictionary from queryset
Build a list of dicts with model instance.title as key and the specs as value by iterating over all Environment model instances.
[{i.title: i.specs} for i in Environment.objects.all()]
Python/Django QuerySet to list of dicts?
other_objs[0]
will be the first element of query and will not be a dict or string but the django model object, you can access attributes like other_objs[0].myattr1
, if you want dict you can ask for specifc attributes using objects.values_list
and then create a dict out of them e.g.
attrs = ['id', 'attr1']
values = Object1.objects.values_list(attrs)[0]
obj_dict = dict(zip(attrs, values))
or you can use django serialization is you want to output dict or json etc, but I think you just need an object, and original query is sufficient.
Convert QuerySet into List in Django for ModelMultipleChoiceField
you can do the following:-
from django.utils.translation import gettext_lazy as _
class Appointment(models.Model):
class TimeSlot(models.TextChoices):
FIRST_T = '5', _('9:00 - 09:30')
SECOND_T = '9', _('09:30 - 10:00')
THIRD_T = '2', _('10:00 - 10:30')
time_slot = models.CharField(max_length=1,choices=TimeSlot.choices,default=TimeSlot.FIRST_T)
class AvailabilitiesForm(forms.Form):
time_slot = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
d1 = kwargs.pop('date')
ava_time = []
for i in Appointment.objects.filter(date=d1):
for x in Appointment.TimeSlot.choices:
if x[0] == i.time_slot:
ava_time.append(x)
self.fields['time_slot'].choices = ava_time
Convert Django Model object to dict with all of the fields intact
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__
instance.__dict__
which returns
{'_foreign_key_cache': <OtherModel: OtherModel object>,
'_state': <django.db.models.base.ModelState at 0x7ff0993f6908>,
'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
'foreign_key_id': 2,
'id': 1,
'normal_value': 1,
'readonly_value': 2}
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
from django.forms.models import model_to_dict
model_to_dict(instance)
which returns
{'foreign_key': 2,
'id': 1,
'many_to_many': [<OtherModel: OtherModel object>],
'normal_value': 1}
This is the only one with many_to_many
, but is missing the uneditable fields.
3.
model_to_dict(..., fields=...)
from django.forms.models import model_to_dict
model_to_dict(instance, fields=[field.name for field in instance._meta.fields])
which returns
{'foreign_key': 2, 'id': 1, 'normal_value': 1}
This is strictly worse than the standard model_to_dict
invocation.
4.
query_set.values()
SomeModel.objects.filter(id=instance.id).values()[0]
which returns
{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
'foreign_key_id': 2,
'id': 1,
'normal_value': 1,
'readonly_value': 2}
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:
from itertools import chain
def to_dict(instance):
opts = instance._meta
data = {}
for f in chain(opts.concrete_fields, opts.private_fields):
data[f.name] = f.value_from_object(instance)
for f in opts.many_to_many:
data[f.name] = [i.id for i in f.value_from_object(instance)]
return data
While this is the most complicated option, calling to_dict(instance)
gives us exactly the desired result:
{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
'foreign_key': 2,
'id': 1,
'many_to_many': [2],
'normal_value': 1,
'readonly_value': 2}
6. Use Serializers
Django Rest Framework's ModelSerializer allows you to build a serializer automatically from a model.
from rest_framework import serializers
class SomeModelSerializer(serializers.ModelSerializer):
class Meta:
model = SomeModel
fields = "__all__"
SomeModelSerializer(instance).data
returns
{'auto_now_add': '2018-12-20T21:34:29.494827Z',
'foreign_key': 2,
'id': 1,
'many_to_many': [2],
'normal_value': 1,
'readonly_value': 2}
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:
from django.db import models
from itertools import chain
class PrintableModel(models.Model):
def __repr__(self):
return str(self.to_dict())
def to_dict(instance):
opts = instance._meta
data = {}
for f in chain(opts.concrete_fields, opts.private_fields):
data[f.name] = f.value_from_object(instance)
for f in opts.many_to_many:
data[f.name] = [i.id for i in f.value_from_object(instance)]
return data
class Meta:
abstract = True
So, for example, if we define our models as such:
class OtherModel(PrintableModel): pass
class SomeModel(PrintableModel):
normal_value = models.IntegerField()
readonly_value = models.IntegerField(editable=False)
auto_now_add = models.DateTimeField(auto_now_add=True)
foreign_key = models.ForeignKey(OtherModel, related_name="ref1")
many_to_many = models.ManyToManyField(OtherModel, related_name="ref2")
Calling SomeModel.objects.first()
now gives output like this:
{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
'foreign_key': 2,
'id': 1,
'many_to_many': [2],
'normal_value': 1,
'readonly_value': 2}
Related Topics
How to Convert Python Code to Application
Pandas Dataframe Calculations With Previous Row
Sub Totals and Grand Totals in Python
How to Ask a Set of Questions Multiple Times Based on User Input
How to Fill Empty Cell Value in Pandas With Condition
How to Read Numbers from File in Python
Json.Decoder.Jsondecodeerror: Expecting Value: Line 1 Column 1 (Char 0) Python
Pyspark - Sum a Column in Dataframe and Return Results as Int
Convert Regular Python String to Raw String
Print() Prints Only Every Second Input
Replacing All Negative Values in Certain Columns by Another Value in Pandas
How to Compile Python Script to Binary Executable
Most Pythonic Way to Kill a Thread After Some Period of Time
How to Iterate Through a List of Dictionaries in Jinja Template
Converting a List into Comma Separated and Add Quotes in Python