如何在 django 中以编程方式恢复 sqlite3 数据库文件



用户希望通过应用程序获得数据库备份和还原功能。他们希望能够下载数据库文件并在需要时上传它以还原数据库。问题是 django 已经在运行当前的数据库文件。我编写了以下逻辑来还原数据库。

folder ='./' 
if request.method == 'POST':        
myfile = request.FILES['file']
fs = FileSystemStorage(location=folder) 
if myfile.name.split(".")[1] != "sqlite3":
return JsonResponse({"res":"Please upload a database file."})
if os.path.isfile(os.path.join(folder, "db.sqlite3")): 
os.remove(os.path.join(folder, "db.sqlite3"))        
filename = fs.save("db.sqlite3", myfile)
file_url = fs.url(filename)
return JsonResponse({"res":file_url})

我得到以下错误,这是正确的:

[WinError 32] 进程无法访问该文件,因为它正由另一个进程使用

那么,有没有办法通过我的应用程序实现此功能?

我找到了使用 csv 创建此功能的更好方法。可以将数据库中的数据存储到 csv 文件中,并在上传时恢复它。以下是我的实现:

def back_up_done(request):
tables = getTableNames()
sql3_cursor = connection.cursor()
for table in tables:
sql3_cursor.execute(f'SELECT * FROM {table}')
with open('output.csv','a') as out_csv_file:
csv_out = csv.writer(out_csv_file)

for result in sql3_cursor:
csv_out.writerow('Null' if x is None else x for x in result)
csv_out.writerow("|")

BaseDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
csv_path = os.path.join(BaseDir, 'output.csv')
dbfile = File(open(csv_path, "rb"))

response = HttpResponse(dbfile, content_type='application/csv')
response['Content-Disposition'] = 'attachment; filename=%s' % 'backup.csv'
response['Content-Length'] = dbfile.size
os.remove(os.path.join("./", "output.csv"))
return response

def back_up_restore(request):
if request.method == 'POST':        
DBfile = request.FILES['file']
cursor = connection.cursor()

if DBfile.name.split(".")[1] != "csv":
messages.add_message(request, messages.ERROR, "Please upload a CSV file.")
return redirect('back-up-db')
tables = getTableNames()
i = 0
deleteColumns()
decoded_file = DBfile.read().decode('utf-8').splitlines()
reader = csv.reader(decoded_file)
for row in reader:
if len(row) != 0:
if(row[0] == "|"):
i += 1
else:
query = f'''Insert into {tables[i]} values({concatRowValues(row)})'''

cursor.execute(query)
connection.close()
messages.add_message(request, messages.SUCCESS, "Data Restored Successfully.")
return redirect('login')
def concatRowValues(row):
data = ''
for i,value in enumerate(row):
if value == "False":
value = '0'
elif value == "True":
value = '1'    

if i != len(row) - 1:
data =  f'{data}{str(value)},' if value == "Null" else f'{data}'{str(value)}','
else:
data = f'{data}{str(value)}' if value == "Null" else f'{data}'{str(value)}''
return data

其中 getTableNames 和 concatRowValues 是帮助程序函数,分别用于获取表的名称和连接列值以形成可执行的 sql 语句。"|"字符用于标记表数据的末尾。

相关内容

最新更新