簡體   English   中英

如何使用字典更新 Django 模型中的字段?

[英]How do I use a dictionary to update fields in Django models?

假設我有一個這樣的模型:

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

我可以創建一個字典,然后使用它插入或更新模型嗎?

d = {"num_pages":40, author:"Jack", date:"3324"}

這是使用字典 d 創建的示例:

Book.objects.create(**d)

要更新現有模型,您需要使用 QuerySet filter方法。 假設您知道要更新的 Book 的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.items(): 
        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()

如果您已經有 Django 對象並且想要更新它的字段,則可以不使用過濾器進行更新。 因為您已經擁有它,在這種情況下,您可能會:

your_obj.__dict__.update(your_dict)
your_obj.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方法具有有限且經過驗證的字段集,手動更新不是這種情況。

要更新一條記錄,您可以使用非常方便的功能:

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

    def update(self,*args, **kwargs):
            for name,values in kwargs.items():
                try:
                    setattr(self,name,values)
                except KeyError:
                    pass
            self.save()

進而:

d = {"num_pages":40, author:"Jack", date:"3324"}
book = Book.objects.first()
book.update(**d)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM