最近的Django項目中有複製記錄的需求。資料庫里有一張名為Party的表,記錄用戶創建的party,現在要讓用戶能夠複製一個新的party。本身非常簡單的一個功能,但運行的時候出錯了。我以為是複製過程出錯,所以測試了一下Django中複製記錄可能遇到的情況(後來發現是其他代碼的邏輯出了問題),結果 ...
最近的Django項目中有複製記錄的需求。資料庫里有一張名為Party的表,記錄用戶創建的party,現在要讓用戶能夠複製一個新的party。本身非常簡單的一個功能,但運行的時候出錯了。我以為是複製過程出錯,所以測試了一下Django中複製記錄可能遇到的情況(後來發現是其他代碼的邏輯出了問題),結果整理如下。
1.Reset pk
在Django中複製一條記錄最簡單的方法應該是先取出這條記錄,將它的主鍵設置為None,然後再保存一次。
Python1 2 3 | old_party = Party.objects.get(pk=1) party.pk = None party.save() |
2.Keyword Arguments
如果某張表除了主鍵還有其他AutoField欄位,就要換一種方式了,雖然也可以手動根據欄位名將其指定為空,但直接遍歷出欄位名和相應的值,把其中的AutoField欄位賦值為None會比較簡單。
Python
1 2 3 4 5 6 7 8 | data = {} for f in old_party._meta.fields: if f.__class__.__name__ != 'AutoField': data[f.name] = getattr(old_party, f.name) else: data[f.name] = None party = Party(**data) party.save() |
3.Deepcopy
Django沒有直接複製記錄的方法,但是Python提供了copy模塊用來拷貝一個對象,所以也可以這樣複製Django的記錄:
Python1 2 3 4 | import copy party = copy.deepcopy(old_party) party.pk = None party.save() |
Except
在關係型資料庫中,存在相關聯的表是很常見的事。Django中有三種關係型欄位:ForeignKey/ManyToManyField/OneToOneField,這些就是需要例外處理的情況了。
ForeignKey在資料庫中是用整數型來存放id,所以只要清空主鍵,直接保存也不會出錯。假設party有一個外鍵關聯到creator,如果要把這個關聯的外鍵也複製一份,可以直接Deepcopy:
Python1 2 3 | creator = copy.deepcopy(party.creator) creator.pk = None creator.save() |
OneToOneField一般都是處理用戶Profile和其他比較特殊的數據,所以還沒有遇到過要複製OneToOneField的情況,純測試了一下,前面提供的方法就可以解決,這裡就不贅述了。
ManyToManyField比較特殊,關聯的一般是多條記錄,需要做一些處理:
Python1 2 3 4 | creator = party.creator.all() party.pk = None party.save() party.creator = creator |