Django и postgresql в docker - Как запустить пользовательский sql для создания представлений после миграции django?

Я хочу создать sql представления после создания таблиц django, так как представления опираются на таблицы, созданные моделями Django.

Проблема заключается в том, что при попытке запустить скрипт python через Dockerfile CMD с вызовом entrypoint.sh
я получаю следующую проблему с именем хоста при попытке подключиться к базе данных postgresql из create_views.py

Я пробовал следующие варианты имен хостов: localhost, db, 0.0.0.0, 127.0.0.1 - безрезультатно.

e.g.

  • psycopg2.OperationalError: connection to server at "0.0.0.0", port 5432 failed: Connection refused
  • не удалось преобразовать имя хоста "db" в адрес: Временный сбой в разрешении имен
  • соединение с сервером на "localhost" (127.0.0.1), порт 5432 не удалось: Connection refused

Я не могу использовать IP-адрес контейнеров, так как при каждом запуске docker-compose up получаются разные IP-адреса для контейнеров...

docker-compose.yml

services:
  app:
    container_name: django-mhb-0.3.1
    build:
      context: .
    ports:
      - "8000:8000"
    volumes:
      - ./myproject/:/app/
    environment:
      - DB_HOST=db
      - DB_NAME=${POSTGRES_DB}
      - DB_USER=${POSTGRES_USER}
      - DB_PWD=${POSTGRES_PASSWORD}
    depends_on:
      - "postgres"

  postgres:
    container_name: postgres-mhb-0.1.1
    image: postgres:14
    volumes:
      - postgres_data:/var/lib/postgresql/data/
      # The following works. However, it runs before the Dockerfile entrypojnt script. 
      # So in this case its trying to create views before the tables exist.
      #- ./myproject/sql/:/docker-entrypoint-initdb.d/
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

volumes:
  postgres_data:

Переменные окружения докера находятся в файле .env в том же каталоге, что и Dockerfile и docker-compose.yml Секреты Django находятся в файле secrets.json в директории проекта django

Dockerfile

### Dockerfile for Django Applications ###

# Pull Base Image
FROM python:3.9-slim-buster AS myapp
# set work directory
WORKDIR /app
# set environment variables
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
# Compiler and OS libraries
RUN apt-get update\
    && apt-get install -y --no-install-recommends build-essential curl libpq-dev \  
    && rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man \
    && apt-get clean \
    && useradd --create-home python
# install dependencies
COPY --chown=python:python ./requirements.txt /tmp/requirements.txt
COPY --chown=python:python ./scripts /scripts
ENV PATH="/home/python/.local/bin:$PATH"
RUN pip install --upgrade pip \
    && pip install -r /tmp/requirements.txt \
    && rm -rf /tmp/requirements.txt  
USER python
# Section 5- Code and User Setup
ENV PATH="/scripts:$PATH"
CMD ["entrypoint.sh"]

entrypoint.sh

#!/bin/sh
echo "start of entrypoint"
set -e
whoami
pwd
#ls -l
#cd ../app/
#ls -l
python manage.py wait_for_db
python manage.py makemigrations
python manage.py migrate
python manage.py djstripe_sync_models product plan
python manage.py shell < docs/build-sample-data.py

## issue arises running this script ##
python manage.py shell < docs/create_views.py

python manage.py runserver 0.0.0.0:8000

create_views.py

#!/usr/bin/env python
import psycopg2 as db_connect

def get_connection():
    try:
        return db_connect.connect(
            database="devdb",
            user="devuser",
            password="devpassword",
            host="0.0.0.0",
            port=5432,
        )
    except (db_connect.Error, db_connect.OperationalError) as e:
        #t_msg = "Database connection error: " + e + "/n SQL: " + s
        print('t_msg ',e)
        return False
try:
    conn = get_connection()
...

Я удалил остальную часть скрипта, так как она не нужна

Когда я запускаю Django/postfgresql вне docker на локальной машине localhost работает нормально.

Надеюсь, кто-нибудь сможет помочь, у меня голова идет кругом, и я уже несколько дней ищу возможный ответ

Спасибо

Благодаря подсказкам Эрика, решено следующим образом

python manage.py makemigrations --empty yourappname

Затем добавил следующее (примечание сокращено для экономии места)

from django.db import migrations

def get_all_items_view(s=None):
    s = ""
    s += "create or replace view v_all_items_report"
    s += " as"
    s += " SELECT project.id, project.slug, project.name as p_name,"
    ...
    return s

def get_full_summary_view(s=None):
    s = ""
    s += "CREATE or replace VIEW v_project_summary"
    s += " AS"
    s += " SELECT project.id, project.slug, project.name as p_name, 
    ...
    return s

class Migration(migrations.Migration):

    dependencies = [
        ('payment', '0002_payment_user'),
    ]

    operations = [
        migrations.RunSQL(get_all_items_view()),
        migrations.RunSQL(get_full_summary_view()),
        migrations.RunSQL(get_invoice_view()),
        migrations.RunSQL(get_payment_view()),
    ]

Обратите внимание на то, чтобы убедиться, что вы перечислили последнюю таблицу, которая должна быть создана в ваших зависимостях, прежде чем будут созданы представления. В моем случае django по умолчанию устанавливает, что все остальные миграции зависят друг от друга в порядке цепочки.

В моем скрипте dockerfile entrypoint.sh находятся команды для создания миграций, миграции и построения некоторых образцов данных

Вернуться на верх