在django中迁移后运行.sql文件

Han*_*nny 1 python django django-models

我在django(非常小的项目)中设置了我的迁移; 但是我有一个.sql文件,它在数据库中有一堆我需要的数据.

在运行迁移之后/期间执行此.sql文件的最佳方式(或者甚至可能)是什么?

sql文件只包含数据的插入,如下所示:

INSERT INTO `mileages_mileages` (`id`, `miles`, `start_location`, `end_location`) VALUES
(NULL,3, 'Location 1', 'Location 2'),
Run Code Online (Sandbox Code Playgroud)

我只需要在运行模型的初始迁移后执行该.sql文件.

那可能吗?

Jel*_*lle 8

migrations.RunSQL()
Run Code Online (Sandbox Code Playgroud)

不接受文件作为输入.只有原始SQL.要解决这个问题,您需要使用:

migrations.RunSQL(
    """
    INSERT INTO 'mileages_mileages' ('id', 'miles', 'start_location', 'end_location') 
    VALUES
       (NULL,3, 'Location 1', 'Location 2');
    """)
Run Code Online (Sandbox Code Playgroud)

要么

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),
    ]
Run Code Online (Sandbox Code Playgroud)


pav*_*roo 5

这是完整的脚本(不完美,但原样),用于将带有 DELIMITER 的 MySQL 语句转换为 SQL 执行。

有关 SQL 语句中的乘法分隔符的信息/sf/answers/3660488331/

在迁移文件中添加脚本执行

有两个使用脚本的示例:运行 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$$
                                                           """
                                                           ))
             ]
Run Code Online (Sandbox Code Playgroud)

脚本文件

# -*- 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
Run Code Online (Sandbox Code Playgroud)

希望它会有所帮助!

  • 您可能需要更新您的示例,因为您使用了错误的注释字符,其中您说过``//添加行,而未满足带有当前分隔符的行```另外,对于使用Python3 StringIO看到此内容的人不在io中模块 EG ```from io import StringIO``` (2认同)

Han*_*nny 2

阅读更多内容后,运行 SQL 来加载迁移中的数据是错误的方法。使用固定装置要好得多。

此后我添加了一个固定装置并将使用该文件来引入数据。

首先,要创建固定装置,我必须将数据添加到表中(我只是手动运行 SQL 文件以将其添加到相应的表中)。

然后我跑了

manage.py dumpdata mileage.mileage --indent 2 --format=json --output initial_mileages.json
Run Code Online (Sandbox Code Playgroud)

这创建了我的装置,然后我加载了它

manage.py loaddata initial_mileages.json
Run Code Online (Sandbox Code Playgroud)

而且导入得很漂亮。