Um dicionário pode ser passado para modelos django no create?

111

É possível fazer algo semelhante a isto com um list, dictionaryou algo mais?

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

Model.objects.create(data_dict)

Melhor ainda se eu puder estendê-lo:

Model.objects.create(data_dict, extra='hello', extra2='world')
Daaawx
fonte

Respostas:

211

Se titlee bodyforem campos em seu modelo, você poderá fornecer os argumentos de palavra-chave em seu dicionário usando o operador ** .

Supondo que seu modelo seja chamado de MyModel:

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

Quanto à sua segunda pergunta, o dicionário deve ser o argumento final. Novamente, extrae extra2devem ser campos no modelo.

m2 =MyModel(extra='hello', extra2='world', **data_dict)
m2.save()
Alasdair
fonte
12
Obrigado, isso é exatamente o que eu estava procurando fazer. Além disso, como nota lateral apenas baseada em sua postagem. Você não precisa chamar o método save ao usar Model.objects.create (** data_dict). Você provavelmente já sabe disso, mas apenas um aviso.
4
Eu nunca usei o objects.createmétodo antes, então você me ensinou algo novo.
Alasdair,
2
também objects.create retorna um ponteiro para o novo modelo, com um pk válido preenchido. Isso significa que você pode usá-lo imediatamente para construir modelos relacionados.
Tom Leys,
10
Eu fui um pouco por ForeignKeys. Se o seu modelo tem um ForeignKeychamado owner, então você data_dictdeve ter um owner_idcampo. Mas django.forms.model_to_dict()retorna um dict com um ownercampo. Então você não pode fazer MyModel(**model_to_dict(my_instance)); você deve renomear o ownercampo para owner_id.
cberzan
A coisa da chave estrangeira (adicionar _id) não funcionou para mim com 1.5.4. Tive que fazer algo mais como modelinstance.save (), modelinstance.add (Foreignobject.id) para uma relação MTM. Obrigado. Isso realmente me ajudou a entrar no caminho certo para fazê-lo funcionar.
RobotHumans
0

Não é uma resposta direta para a pergunta, mas acho que este código me ajudou a criar os dictos que economizam bem na resposta correta. As conversões de tipo feitas são necessárias se esses dados forem exportados para json.

Eu espero que isso ajude:

  #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
fonte