在Django中需要向數據庫中插入多條數據(list)。使用如下方法,每次save()的時候都會訪問一次數據庫。導致性能問題:
for i in resultlist:
p = Account(name=i)
p.save()
在django1.4以后加入了新的特性。使用django.db.models.query.QuerySet.bulk_create()批量創建對象,減少SQL查詢次數。改進如下:
querysetlist=[]
for i in resultlist:
querysetlist.append(Account(name=i))
Account.objects.bulk_create(querysetlist)
Model.objects.bulk_create() 更快更方便
常規用法:
#!/usr/bin/env python
#coding:utf-8
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'''
Django 版本大於等於1.7的時候,需要加上下面兩句
import django
django.setup()
否則會拋出錯誤 django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
'''
import django
if django.VERSION >= (1, 7):#自動判斷版本
django.setup()
def main():
from blog.models import Blog
f = open('oldblog.txt')
for line in f:
title,content = line.split('****')
Blog.objects.create(title=title,content=content)
f.close()
if __name__ == "__main__":
main()
print('Done!')
使用批量導入:
#!/usr/bin/env python
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
def main():
from blog.models import Blog
f = open('oldblog.txt')
BlogList = []
for line in f:
title,content = line.split('****')
blog = Blog(title=title,content=content)
BlogList.append(blog)
f.close()
Blog.objects.bulk_create(BlogList)
if __name__ == "__main__":
main()
print('Done!')
由於Blog.objects.create()
每保存一條就執行一次SQL,而bulk_create()
是執行一條SQL存入多條數據,做會快很多!當然用列表解析代替 for 循環會更快!!
#!/usr/bin/env python
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
def main():
from blog.models import Blog
f = open('oldblog.txt')
BlogList = []
for line in f:
parts = line.split('****')
BlogList.append(Blog(title=parts[0], content=parts[1]))
f.close()
# 以上四行 也可以用 列表解析 寫成下面這樣
# BlogList = [Blog(title=line.split('****')[0], content=line.split('****')[1]) for line in f]
Blog.objects.bulk_create(BlogList)
if __name__ == "__main__":
main()
print('Done!')
批量導入時數據重復的解決方法
如果你導入數據過多,導入時出錯了,或者你手動停止了,導入了一部分,還有一部分沒有導入。或者你再次運行上面的命令,你會發現數據重復了,怎么辦呢?
django.db.models
中還有一個函數叫 get_or_create()
,之前文章中也提到過,有就獲取過來,沒有就創建,用它可以避免重復,但是速度可以會慢些,因為要先嘗試獲取,看看有沒有
只要把上面的:
Blog.objects.create(title=title,content=content)
換成下面的就不會重復導入數據了
Blog.objects.get_or_create(title=title,content=content)
返回值是(BlogObject, True/False)
新建時返回 True, 已經存在時返回 False。