В Django 2.1 я хотел загрузить некоторые модели (например, названия стран) с исходными данными.
Но я хотел, чтобы это происходило автоматически сразу после выполнения начальных миграций.
Поэтому я подумал, что было бы здорово иметь sql/
папку внутри каждого приложения, которое требует загрузки исходных данных.
Затем в этой sql/
папке у меня будут .sql
файлы с необходимыми DML для загрузки исходных данных в соответствующие модели, например:
INSERT INTO appName_modelName(fieldName)
VALUES
("country 1"),
("country 2"),
("country 3"),
("country 4");
Чтобы быть более наглядным, вот как sql/
будет выглядеть приложение, содержащее папку:
Также я нашел несколько случаев, когда мне нужно было, чтобы sql
скрипты выполнялись в определенном порядке. Поэтому я решил поставить перед именами файлов порядковый номер, как показано на изображении выше.
Затем мне понадобился способ SQLs
автоматически загружать все, что есть в любой папке приложения, путем выполнения python manage.py migrate
.
Итак, я создал другое приложение с именем, initial_data_migrations
а затем добавил это приложение в список INSTALLED_APPS
в settings.py
файле. Затем я создал migrations
внутри папку и добавил файл с именем run_sql_scripts.py
( который на самом деле является настраиваемой миграцией ). Как видно на изображении ниже:
Я создал run_sql_scripts.py
так, чтобы он заботился о запуске всех sql
скриптов, доступных в каждом приложении. Этот затем запускается, когда кто-то бежит python manage.py migrate
. Этот обычай migration
также добавляет задействованные приложения в качестве зависимостей, таким образом он пытается запускать sql
операторы только после того, как требуемые приложения выполнили свои 0001_initial.py
миграции (мы не хотим пытаться запустить оператор SQL для несуществующей таблицы).
Вот источник этого сценария:
import os
import itertools
from django.db import migrations
from YourDjangoProjectName.settings import BASE_DIR, INSTALLED_APPS
SQL_FOLDER = "/sql/"
APP_SQL_FOLDERS = [
(os.path.join(BASE_DIR, app + SQL_FOLDER), app) for app in INSTALLED_APPS
if os.path.isdir(os.path.join(BASE_DIR, app + SQL_FOLDER))
]
SQL_FILES = [
sorted([path + file for file in os.listdir(path) if file.lower().endswith('.sql')])
for path, app in APP_SQL_FOLDERS
]
def load_file(path):
with open(path, 'r') as f:
return f.read()
class Migration(migrations.Migration):
dependencies = [
(app, '__first__') for path, app in APP_SQL_FOLDERS
]
operations = [
migrations.RunSQL(load_file(f)) for f in list(itertools.chain.from_iterable(SQL_FILES))
]
Я надеюсь, что кто-то сочтет это полезным, у меня все сработало! Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать.
ПРИМЕЧАНИЕ. Возможно, это не лучшее решение, так как я только начинаю работать с django, но все же хотел поделиться этим «Практическим руководством» со всеми вами, так как я не нашел много информации, пока гуглил об этом.