This commit is contained in:
62
scripts/fix_profiles_fk.sh
Executable file
62
scripts/fix_profiles_fk.sh
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# 1) Обновим модель Photo: добавим ForeignKey + нормальную relationship
|
||||
cat > services/profiles/src/app/models/photo.py <<'PY'
|
||||
from __future__ import annotations
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import String, Boolean, DateTime, ForeignKey
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.db.session import Base
|
||||
|
||||
class Photo(Base):
|
||||
__tablename__ = "photos"
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
profile_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("profiles.id", ondelete="CASCADE"),
|
||||
index=True,
|
||||
nullable=False,
|
||||
)
|
||||
url: Mapped[str] = mapped_column(String(500), nullable=False)
|
||||
is_main: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
status: Mapped[str] = mapped_column(String(16), default="pending") # pending/approved/rejected
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
|
||||
profile = relationship("Profile", back_populates="photos")
|
||||
PY
|
||||
|
||||
# (необязательно, но полезно) поправим типы JSONB в Profile
|
||||
awk '
|
||||
{print}
|
||||
/languages:/ && $0 ~ /dict/ { sub(/dict \| None/, "list[str] | None"); print "# (autofixed: changed languages type to list[str])"}
|
||||
/interests:/ && $0 ~ /dict/ { sub(/dict \| None/, "list[str] | None"); print "# (autofixed: changed interests type to list[str])"}
|
||||
' services/profiles/src/app/models/profile.py > services/profiles/src/app/models/profile.py.tmp \
|
||||
&& mv services/profiles/src/app/models/profile.py.tmp services/profiles/src/app/models/profile.py || true
|
||||
|
||||
# 2) Сгенерируем ревизию Alembic (сравнить модели с БД)
|
||||
docker compose up -d postgres
|
||||
docker compose run --rm -v "$PWD/services/profiles":/app profiles \
|
||||
sh -lc 'alembic revision --autogenerate -m "add FK photos.profile_id -> profiles.id"'
|
||||
|
||||
# 3) Если автогенерация не добавила FK — вживлём вручную в последнюю ревизию
|
||||
LAST=$(ls -1t services/profiles/alembic/versions/*.py | head -n1)
|
||||
if ! grep -q "create_foreign_key" "$LAST"; then
|
||||
# вставим импорт postgresql (на будущее) и create_foreign_key в upgrade()
|
||||
sed -i '/import sqlalchemy as sa/a from sqlalchemy.dialects import postgresql' "$LAST"
|
||||
awk '
|
||||
BEGIN{done=0}
|
||||
/def upgrade/ && done==0 {print; print " op.create_foreign_key("; print " '\''fk_photos_profile_id_profiles'\'',"; print " '\''photos'\'', '\''profiles'\'',"; print " ['\''profile_id'\''], ['\''id'\''],"; print " ondelete='\''CASCADE'\''"; print " )"; done=1; next}
|
||||
{print}
|
||||
' "$LAST" > "$LAST.tmp" && mv "$LAST.tmp" "$LAST"
|
||||
fi
|
||||
|
||||
# 4) Применим миграции и перезапустим сервис
|
||||
docker compose run --rm profiles alembic upgrade head
|
||||
docker compose restart profiles
|
||||
Reference in New Issue
Block a user