2009-10-16 41 views
43

Tôi tự hỏi, một cách tiêu chuẩn để cập nhật nhiều trường của một cá thể của một mô hình trong django là gì? ... Nếu tôi có một mô hình với một số lĩnh vực,Làm thế nào để cập nhật nhiều trường của một cá thể mô hình django?

Class foomodel(models.Model): 
    field1 = models.CharField(max_length=10) 
    field2 = models.CharField(max_length=10) 
    field3 = models.CharField(max_length=10) 
    ... 

... và tôi nhanh chóng nó với một lĩnh vực nhất định, và sau đó trong một bước riêng biệt Tôi muốn cung cấp phần còn lại của các lĩnh vực, làm cách nào để làm điều đó bằng cách chỉ cần chuyển từ điển hoặc thông số giá trị khóa? Khả thi?

Nói cách khác, nói rằng tôi có một từ điển với một số dữ liệu trong đó có mọi thứ tôi muốn viết vào một thể hiện của mô hình đó. Ví dụ mô hình đã được khởi tạo trong một bước riêng biệt và giả sử nó chưa được duy trì. Tôi có thể nói foo_instance.field1 = my_data_dict['field1'] cho mỗi trường, nhưng một cái gì đó cho tôi biết phải có một cách gọi một phương thức trên cá thể mô hình mà tôi chỉ chuyển tất cả các cặp giá trị trường cùng một lúc và cập nhật chúng. Một cái gì đó như foo_instance.update(my_data_dict). Tôi không thấy bất kỳ phương pháp được xây dựng trong như thế này, tôi có thiếu nó hay làm thế nào điều này được thực hiện hiệu quả?

Tôi có cảm giác đây là một loại câu hỏi RTM rõ ràng nhưng tôi chưa thấy nó trong tài liệu.

Trả lời

93

Đó là hấp dẫn để gây rối với __dict__, nhưng điều đó sẽ không áp dụng đối với các thuộc tính kế thừa từ một lớp cha mẹ.

Bạn có thể lặp qua các dict để gán cho các đối tượng:

for (key, value) in my_data_dict.items(): 
    setattr(obj, key, value) 

Hoặc bạn có thể trực tiếp sửa đổi nó từ một queryset (đảm bảo truy vấn của bạn chỉ đặt trả về đối tượng bạn quan tâm):

FooModel.objects.filter(whatever="anything").update(**my_data_dict) 
+0

có hoạt động với các trường m2m không? –

24

Bạn có thể thử này:

obj.__dict__.update(my_data_dict) 
+6

này sẽ không áp dụng đối với các thuộc tính kế thừa. –

+1

Các tác động của thực tế là nó sẽ không áp dụng cho các thuộc tính kế thừa là gì? –

+0

Ngoài ra, bạn đang cố gắng cập nhật ForeignKey, sử dụng __dict__, tên giá trị có liên quan là 'field_name_id' không phải là' field_name', bạn cần phải cẩn thận với điều đó. – levi

3

Có vẻ như một điều tự nhiên bạn muốn làm nhưng cũng giống như bạn cũng không tìm thấy nó trong tài liệu. Các tài liệu nói rằng bạn nên sub-class save() trên mô hình. Và đó là những gì tôi làm.

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() 
+1

Suy nghĩ tạo trang trí cho các mô hình thêm phương thức mới "dict_save" (do đó, 2 phương pháp lưu cho mô hình - bình thường và dict) với phần thân bên trên vào lần sau tôi cần. Tôi nhìn lên mã tôi đã sử dụng để làm điều này và nó giống nhau, ngoại trừ việc tôi đã làm nó bên ngoài tiết kiệm.Đã có một phương thức update_model_obj_from_dict (model_object, update_dict) với hầu như cùng một phần thân như trên và mong rằng tôi sẽ chọn khi nào gọi save() sau. Tôi giống như có sự lựa chọn. vì vậy có lẽ một phương thức trên mô hình được gọi là "set_from_dict" với mọi thứ ở trên trừ dòng cuối cùng và chỉ sử dụng lưu sau này. – Purrell

2

tôi nhận được tên khóa chính của, sử dụng nó để lọc với Queryset.filter() và cập nhật với 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) 

Điều này cho phép tôi cập nhật phiên bản bất kỳ khóa chính nào.

1

Cập nhật bằng 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) 
+0

Chào mừng bạn đến với SO. Khi đăng câu trả lời, vui lòng bao gồm giải thích về mã của bạn và nhớ định dạng văn bản. – Tony

Các vấn đề liên quan