146

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
  • 3,273
  • 2
  • 17
  • 16

3 Answers3

282

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
  • 298,606
  • 55
  • 578
  • 516
  • 15
    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
  • 12
    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
  • @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
  • In Django 4. x, No need for m.sasve() anymore. It will return a tuple, `obj, is_created = Model.objects.get_or_create(**dic)` – bobo pei Nov 16 '22 at 13:49
  • @bobopei `Model.objects.create(**data_dict)` would probably be better. I would only use `get_or_create` if I expected there would be duplicates and needed to handle them. – Alasdair Nov 17 '22 at 14:51
1

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

codehia
  • 124
  • 2
  • 4
  • 16
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,275
  • 23
  • 30