ジャンゴのモデルのインスタンスの複数のフィールドを更新する標準的な方法は何ですか? ...いくつかのフィールドを持つモデルがある場合、
_Class foomodel(models.Model):
field1 = models.CharField(max_length=10)
field2 = models.CharField(max_length=10)
field3 = models.CharField(max_length=10)
...
_
...そして、1つのフィールドを指定してインスタンス化し、別のステップで残りのフィールドを提供したいのですが、辞書またはキー値のパラメーターを渡すだけでそれを行うにはどうすればよいですか?可能?
言い換えれば、そのモデルのインスタンスに書き込みたいすべてのものを含むいくつかのデータを含む辞書があるとしましょう。モデルインスタンスは別のステップでインスタンス化されており、まだ永続化されていないとしましょう。各フィールドに対して_foo_instance.field1 = my_data_dict['field1']
_と言うことができますが、モデルインスタンスでメソッドを呼び出す方法が必要であることがわかり、フィールド値のペアをすべて一度に渡して更新します。 foo_instance.update(my_data_dict)
のようなもの。このような組み込みメソッドは表示されませんが、欠落しているのですか、これはどのように効率的に行われますか?
RTM一種の質問ですが、ドキュメントでは見ていません。
__dict__
をいじるのは魅力的ですが、親クラスから継承された属性には適用されません。
Dictを反復処理して、オブジェクトに割り当てることができます。
for (key, value) in my_data_dict.items():
setattr(obj, key, value)
または、クエリセットから直接変更することもできます(クエリセットが目的のオブジェクトのみを返すことを確認してください)。
FooModel.objects.filter(whatever="anything").update(**my_data_dict)
これを試すことができます:
obj.__dict__.update(my_data_dict)
あなたがしたいと思うような自然なことのように思えますが、あなたのように私もドキュメントでそれを見つけませんでした。ドキュメントには、モデルのsave()をサブクラス化する必要があると書かれています。そして、それが私がしていることです。
def save(self, **kwargs):
mfields = iter(self._meta.fields)
mods = [(f.attname, kwargs[f.attname]) for f in mfields if f.attname in kwargs]
for fname, fval in mods: setattr(self, fname, fval)
super(MyModel, self).save()
主キーの名前を取得し、それを使用してQueryset.filter()
でフィルタリングし、Queryset.update()
で更新します。
fooinstance = ...
# Find primary key and make a dict for filter
pk_name foomodel._meta.pk.name
filtr = {pk_name: getattr(fooinstance, pk_name)}
# Create a dict attribute to update
updat = {'name': 'foo', 'lastname': 'bar'}
# Apply
foomodel.objects.filter(**filtr).update(**updat)
これにより、主キーに関係なくインスタンスを更新できます。
update()
を使用して更新する
Discussion.objects.filter(slug=d.slug)
.update(title=form_data['title'],
category=get_object_or_404(Category, pk=form_data['category']),
description=form_data['description'], closed=True)