我在django(非常小的项目)中设置了我的迁移;但是我有一个.sql文件,它在数据库中有一堆我需要的数据。
在运行迁移之后/期间执行此.sql文件的最佳方法是什么(或者甚至可能)?
sql文件只包含这样的数据插入:
INSERT INTO `mileages_mileages` (`id`, `miles`, `start_location`, `end_location`) VALUES
(NULL,3, 'Location 1', 'Location 2'),
我只需要在运行模型的初始迁移后执行该.sql文件。
这可能吗?
答案 0 :(得分:6)
migrations.RunSQL()
不接受文件作为输入。只有原始SQL。要解决此问题,您需要使用:
migrations.RunSQL(
"""
INSERT INTO 'mileages_mileages' ('id', 'miles', 'start_location', 'end_location')
VALUES
(NULL,3, 'Location 1', 'Location 2');
""")
或
def load_data_from_sql(apps, schema_editor):
file_path = os.path.join(os.path.dirname(__file__), 'file_name.sql')
sql_statement = open(file_path).read()
with connection.cursor() as c:
c.execute(sql_statement)
class Migration(migrations.Migration):
dependencies = [
('..', '...'),
]
operations = [
migrations.RunPython(load_data_from_sql),
]
答案 1 :(得分:1)
使用migrations.RunSQL
时,如果出现以下错误:
如果不分割SQL,则sqlparse是必需的
您只需要安装sqlparse
即可解决问题:
pip install sqlparse
答案 2 :(得分:0)
您可以执行原始SQL
operations = [
migrations.RunSQL('sql statement here')
]
答案 3 :(得分:0)
在阅读了一下之后 - 运行SQL以在迁移中加载数据是错误的方法。使用fixtures要好得多。
我已经添加了一个灯具,并将使用该文件来引入数据。
首先,要创建夹具,我必须将我的数据添加到表中(我只是手动运行SQL文件以将其添加到相应的表中)。
然后我跑了
manage.py dumpdata mileage.mileage --indent 2 --format=json --output initial_mileages.json
创建了我的夹具,然后我加载了
manage.py loaddata initial_mileages.json
它导入得很漂亮。
答案 4 :(得分:0)
这里是将带有DELIMITER的MySQL语句转换为SQL执行的完整脚本(不是很完美,但仍是这样)。
SQL语句https://stackoverflow.com/a/52292690/9521312中有关乘法定界符的信息
有两个使用脚本的示例:运行sql文件或运行原始MySQL语句
from anywhere import migrate_run_sql
operations = [
migrations.RunPython(migrate_run_sql.run_sql_file('contract_triggers.sql')),
migrations.RunPython(migrate_run_sql.run_sql(
"""
DELIMITER $$
CREATE TRIGGER trigger_name BEFORE INSERT ON table
FOR EACH ROW
BEGIN
IF NEW.number <> 'anynumber' AND NEW.number <> 'anynumber'
THEN
SET NEW.number = 'anynumber';
END IF;
END$$
"""
))
]
# -*- coding: utf-8 -*-
from django.db import connection
import re
from StringIO import StringIO
from django.conf import settings
import os
# this function get raw MySQL statement
def run_sql(sql):
def load_data_from_sql(app, schema_editor):
f = StringIO(sql)
return _runsql(f)
return load_data_from_sql
# this function get sql file
def run_sql_file(filename):
def load_data_from_sql(app, schema_editor):
filepath = os.path.join(settings.PROJECT_PATH, '../deploy/mysql/', filename)
with open(filepath, 'rb') as f:
return _runsql(f)
return load_data_from_sql
# in this function content splits and checks line by line
def _runsql(f):
with connection.cursor() as c:
file_data = f.readlines()
statement = ''
delimiter = ';\n'
for line in file_data:
if re.findall('DELIMITER', line): # found delimiter
if re.findall('^\s*DELIMITER\s+(\S+)\s*$', line):
delimiter = re.findall('^\s*DELIMITER\s+(\S+)\s*$', line)[0] + '\n'
continue
else:
raise SyntaxError('Your usage of DELIMITER is not correct, go and fix it!')
statement += line // add lines while not met lines with current delimiter
if line.endswith(delimiter):
if delimiter != ';\n':
statement = statement.replace(';', '; --').replace(delimiter, ';') # found delimiter, add dash symbols (or any symbols you want) for converting MySQL statements with multiply delimiters in SQL statement
c.execute(statement) # execute current statement
statement = '' # begin collect next statement
希望这会有所帮助!