W Django 2.1 chciałem załadować niektóre modele (na przykład nazwy krajów) z danymi początkowymi.
Ale chciałem, żeby stało się to automatycznie zaraz po wykonaniu początkowych migracji.
Pomyślałem więc, że byłoby wspaniale mieć sql/
folder w każdej aplikacji, który wymagałby załadowania danych początkowych.
Następnie w tym sql/
folderze miałbym .sql
pliki z wymaganymi plikami DML, aby załadować dane początkowe do odpowiednich modeli, na przykład:
INSERT INTO appName_modelName(fieldName)
VALUES
("country 1"),
("country 2"),
("country 3"),
("country 4");
Aby być bardziej opisowym, tak wyglądałaby aplikacja zawierająca sql/
folder:
Znalazłem również przypadki, w których potrzebowałem sql
skryptów do wykonania w określonej kolejności. Postanowiłem więc poprzedzić nazwy plików kolejnym numerem, jak widać na powyższym obrazku.
Potem potrzebowałem sposobu, aby automatycznie załadować wszystkie SQLs
dostępne w dowolnym folderze aplikacji, wykonując python manage.py migrate
.
Utworzyłem więc inną aplikację o nazwie, initial_data_migrations
a następnie dodałem tę aplikację do listy INSTALLED_APPS
w settings.py
pliku. Następnie utworzyłem migrations
folder w środku i dodałem plik o nazwie run_sql_scripts.py
( co w rzeczywistości jest niestandardową migracją ). Jak widać na poniższym obrazku:
Stworzyłem run_sql_scripts.py
tak, aby zadbał o uruchomienie wszystkich sql
skryptów dostępnych w ramach każdej aplikacji. Ten jest następnie odpalany, gdy ktoś biegnie python manage.py migrate
. Ten niestandardowy migration
dodaje również zaangażowane aplikacje jako zależności, w ten sposób próbuje uruchomić sql
instrukcje dopiero po wykonaniu 0001_initial.py
migracji przez wymagane aplikacje (nie chcemy próbować uruchamiać instrukcji SQL na nieistniejącej tabeli).
Oto źródło tego skryptu:
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))
]
Mam nadzieję, że ktoś uzna to za pomocne, działało dobrze dla mnie !. Jeśli masz jakieś pytania, daj mi znać.
UWAGA: To może nie być najlepsze rozwiązanie, ponieważ dopiero zaczynam pracę z django, jednak nadal chciałem się z wami podzielić tym "Jak to zrobić", ponieważ nie znalazłem zbyt wielu informacji podczas wyszukiwania go w Google.