141

Is it possible to do something similar to this with a list, dictionary or something else?

data_dict = {
    'title' : 'awesome title',
    'body' : 'great body of text',
}

Model.objects.create(data_dict)

Even better if I can extend it:

Model.objects.create(data_dict, extra='hello', extra2='world')
daaawx
  • 2,798
  • 2
  • 14
  • 15

3 Answers3

271

If title and body are fields in your model, then you can deliver the keyword arguments in your dictionary using the ** operator.

Assuming your model is called MyModel:

# create instance of model
m = MyModel(**data_dict)
# don't forget to save to database!
m.save()

As for your second question, the dictionary has to be the final argument. Again, extra and extra2 should be fields in the model.

m2 =MyModel(extra='hello', extra2='world', **data_dict)
m2.save()
Alasdair
  • 278,338
  • 51
  • 534
  • 489
  • 14
    Thanks, that is exactly what I was looking to do. Also, as a side note just based off your post. You don't have to call the save method when using Model.objects.create(**data_dict). You probably already know this but just a heads up. –  Oct 15 '09 at 14:00
  • 5
    I've not used the `objects.create` method before, so you've taught me something new. – Alasdair Oct 15 '09 at 14:13
  • 2
    also objects.create returns a pointer to the new model, with a valid pk filled in. This means you can immediately use it to build related models. – Tom Leys Oct 16 '09 at 06:21
  • 11
    I got bit by `ForeignKey`s. If your model has a `ForeignKey` called `owner`, then your `data_dict` should have an `owner_id` field. But `django.forms.model_to_dict()` returns a dict with an `owner` field. So you can't do `MyModel(**model_to_dict(my_instance))`; you have to rename the `owner` field to `owner_id`. – cberzan Mar 02 '12 at 01:45
  • 1
    The foreign key thing (adding _id) didn't work for me with 1.5.4. I had to do something more like modelinstance.save(), modelinstance.add(foreignobject.id) for a MTM relation. Thanks though. This really helped me get on the right track to getting it working. – RobotHumans Oct 06 '13 at 12:37
  • That is a good point about model_to_dict naming of keys. I use __dict__ of a model (m2.__dict__, the keys are named correctly and it doesn't add the extra stuff you may/maynot want. Note there are some hidden fields you'll want to remove, they all start wtih an _ – Luke Dupin Oct 01 '15 at 23:30
  • For some reason, when I pass a dictionary to my model, there's some weird truncating behaviour that is happening now, with the new version of django. – Paul von Hoesslin Dec 10 '21 at 12:28
  • @PaulvonHoesslin you’re more likely to get an answer if you ask a new question and include code to reproduce the issue – Alasdair Dec 10 '21 at 13:19
1

For any model DummyModel you can use DummyModel.objects.create(**data_dict). Does not require save after the create.

codehia
  • 152
  • 1
  • 4
  • 15
0

Not directly an answer to the question, but I find this code helped me create the dicts that save nicely into the correct answer. The type conversions made are required if this data will be exported to json.

I hope this helps:

  #mod is a django database model instance
def toDict( mod ):
  import datetime
  from decimal import Decimal
  import re

    #Go through the object, load in the objects we want
  obj = {}
  for key in mod.__dict__:
    if re.search('^_', key):
      continue

      #Copy my data
    if isinstance( mod.__dict__[key], datetime.datetime ):
      obj[key] = int(calendar.timegm( ts.utctimetuple(mod.__dict__[key])))
    elif isinstance( mod.__dict__[key], Decimal ):
      obj[key] = float( mod.__dict__[key] )
    else:
      obj[key] = mod.__dict__[key]

  return obj 

def toCsv( mod, fields, delim=',' ):
  import datetime
  from decimal import Decimal

    #Dump the items
  raw = []
  for key in fields:
    if key not in mod.__dict__:
      continue

      #Copy my data
    if isinstance( mod.__dict__[key], datetime.datetime ):
      raw.append( str(calendar.timegm( ts.utctimetuple(mod.__dict__[key]))) )
    elif isinstance( mod.__dict__[key], Decimal ):
      raw.append( str(float( mod.__dict__[key] )))
    else:
      raw.append( str(mod.__dict__[key]) )

  return delim.join( raw )
Luke Dupin
  • 2,091
  • 19
  • 28