次のようなモデルがあるとします:
class Book(models.Model):
num_pages = ...
author = ...
date = ...
辞書を作成し、それを使用してモデルを挿入または更新できますか?
d = {"num_pages":40, author:"Jack", date:"3324"}
辞書dを使用して作成する例を次に示します。
Book.objects.create(**d)
既存のモデルを更新するには、QuerySet filter
メソッドを使用する必要があります。更新する本のpk
を知っていると仮定します:
Book.objects.filter(pk=pk).update(**d)
作成することがわかっている場合:
Book.objects.create(**d)
既存のインスタンスを確認する必要がある場合、getまたはcreateで検索できます。
instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
for attr, value in d.iteritems():
setattr(instance, attr, value)
instance.save()
別の回答で述べたように、クエリセットマネージャーでupdate
関数を使用することもできますが、信号を送信しません(それらを使用していない場合は問題になりません)。ただし、単一のオブジェクトを変更するために使用しないでください。
Book.objects.filter(id=id).update()
_**
_を使用して、新しいモデルを作成します。辞書をループして、setattr()
を使用して既存のモデルを更新します。
Tom ChristieのDjango Rest Frameworkから
https://github.com/tomchristie/Django-rest-framework/blob/master/rest_framework/serializers.py
_for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
_
他の回答に加えて、関連フィールドとの干渉を防ぐためのもう少し安全なバージョンがあります。
def is_simple_editable_field(field):
return (
field.editable
and not field.primary_key
and not isinstance(field, (ForeignObjectRel, RelatedField))
)
def update_from_dict(instance, attrs, commit):
allowed_field_names = {
f.name for f in instance._meta.get_fields()
if is_simple_editable_field(f)
}
for attr, val in attrs.items():
if attr in allowed_field_names:
setattr(instance, attr, val)
if commit:
instance.save()
更新しようとしているフィールドが編集可能であり、主キーではなく、関連するフィールドでもないことを確認します。
使用例:
book = Book.objects.first()
update_from_dict(book, {"num_pages":40, author:"Jack", date:"3324"})
高級DRFシリアライザー.create
および.update
メソッドには、限られた検証済みのフィールドセットがありますが、手動更新の場合はそうではありません。