Bagaimana menyederhanakan migrasi di Django 1.7?

92

Sudah ada pertanyaan serupa untuk Selatan, tetapi saya telah memulai proyek saya dengan Django 1.7 dan saya tidak menggunakan Selatan.

Selama pengembangan, banyak migrasi telah dibuat, namun perangkat lunak belum dikirim dan tidak ada database yang harus dimigrasi. Oleh karena itu saya ingin mengatur ulang migrasi seolah-olah model saya saat ini adalah yang asli dan membuat ulang semua database.

Apa cara yang disarankan untuk melakukan itu?

EDIT: Pada Django 1.8 ada perintah baru bernama squashmigrations yang kurang lebih memecahkan masalah yang dijelaskan di sini.

Kit Fisto
sumber
Apa yang dimaksud dengan menyetel ulang migrasi? Batalkan?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Jawaban:

137

Saya mengerti. Saya baru saja menemukan ini dan itu bagus.

  • Pertama, untuk menghapus tabel migrasi:

    ./manage.py migrate --fake <app-name> zero
  • Hapus app-name/migrations/folder atau konten.

  • Lakukan migrasi:

    ./manage.py makemigrations <app-name>
  • Terakhir, rapikan migrasi Anda tanpa membuat perubahan database lainnya:

    ./manage.py migrate --fake <app-name>
kzorro.dll
sumber
5
Ini jawaban yang bagus. Hanya menghapus migrasi tidak membatalkan kerusakan yang disebabkan oleh migrasi. Ini benar-benar membersihkan batu tulis dan memungkinkan Anda memulai kembali.
rogueleaderr
15
Jika Anda ingin menjelaskan sedikit, ini harus menjadi jawaban yang diterima.
tani-rokk
8
Jawaban satu baris yang bagus bro, saya tidak tahu apa fungsinya
bischoffingston
13
Garis ini hanya membalikkan migrasi satu per satu, sampai zero. Untuk sistem migrasi Django, <app-name> sekarang menjadi aplikasi baru dan makemigrations <app-name>akan dimulai dari 0001. --fakemencegah tabel agar tidak benar-benar diubah, bahwa migrasi seharusnya hanya ditandai terbalik dan tidak benar-benar diterapkan ke skema. (Menambahkan penjelasan kecil demi kelengkapan, @ tani-rokk, @Fabrizio)
Mir Nazim
17
manage.py migrate --fake <app-name> zerountuk menghapus tabel migrasi, lalu hapus <app-name> / migrations / folder atau konten. Kemudian manage.py makemigrations <app-name>dan akhirnya lakukan manage.py migrate --fake <app-name>. Ini akan merapikan migrasi Anda tanpa membuat perubahan database lainnya.
doeke
36

Dalam migrasi versi Django 1.7 fungsionalitas reset yang dulu di Selatan telah dihapus untuk mendukung fungsionalitas baru untuk 'menekan' migrasi Anda. Ini seharusnya menjadi cara yang baik untuk menjaga jumlah migrasi tetap terkendali.

https://docs.djangoproject.com/en/dev/topics/migrations/#squashing-migrations

Jika Anda masih ingin benar-benar memulai dari awal, saya berasumsi Anda masih bisa dengan mengosongkan tabel migrasi dan menghapus migrasi setelah itu Anda akan berjalan makemigrationslagi.

tijs
sumber
2
Bagaimana cara "menghapus migrasi" selain mengosongkan tabel migrasi? Apakah saya akan menghapus seluruh folder atau hanya file 00X _ *. Py?
Kit Fisto
dengan South Anda dapat menghapus folder migrasi yang akan dibuat ulang ketika Anda menjalankan makemigrations lagi. Saya berasumsi ini bekerja sama untuk Django 1.7
tijs
4
Hanya sebuah catatan. di Django 1.7, jika anda, tidak hati-hati, menghapus folder migrasi itu mungkin memunculkan pengecualian jika model anda adalah anak dari model lainraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algoritmatik
Secara khusus ./manage.py squashmigrations myapp 0004akan menghentikan semua migrasi sebelum migrasi 0004di aplikasi Anda myapp. Ini akan membuat satu migrasi terjepit.
Bryce Guinta
22

Saya baru saja mengalami masalah yang sama. Inilah solusi saya.

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete


# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

Itu find perintah: http://unixhelp.ed.ac.uk/CGI/man-cgi?find

Abdelhamid Belarbi
sumber
13
ini menghapus data, tidak hanya migrasi
kompor
2
Anda harus menghapus file
.pyc
7

Dengan asumsi ini adalah struktur proyek Anda,

project_root/
    app1/
        migrations/
    app2/
        migrations/
    ...
    manage.py
    remove_migrations.py

Anda dapat menjalankan skrip remove_migrations.py dari tempat yang ditunjukkan di atas untuk menghapus semua file migrasi.

#remove_migrations.py
"""
Run this file from a Django =1.7 project root. 
Removes all migration files from all apps in a project.
""" 
from unipath import Path

this_file = Path(__file__).absolute()
current_dir = this_file.parent
dir_list = current_dir.listdir()

for paths in dir_list:
    migration_folder = paths.child('migrations')
    if migration_folder.exists():
        list_files = migration_folder.listdir()
        for files in list_files:
            split = files.components()
            if split[-1] != Path('__init__.py'):
                files.remove()

Menghapus secara manual bisa melelahkan jika Anda memiliki proyek yang rumit. Ini menghemat banyak waktu saya. Menghapus file migrasi aman. Saya telah melakukan ini beberapa kali tanpa menghadapi masalah ... belum.

Namun ketika saya menghapus folder migrasi, makemigrationsatau migratetidak membuat folder kembali untuk saya. Skrip memastikan bahwa folder migrasi dengan foldernya __init__.pytetap ada, hanya menghapus file migrasi.


sumber
Anda bisa saja menghapus folder migrasi dan membuatnya kembali dengan init .py kosong (misalnya touch migrations/__init__.py)
kompor
6
  1. Hapus file: delete_migrations.py (di root prj):
import os

for root, dirs, files in os.walk(".", topdown=False):
  for name in files:
      if '/migrations' in root and name != '__init__.py':
          os.remove(os.path.join(root, name))
  1. DELETE FROM django_migrations Where app in ('app1', 'app2');

  2. ./manage.py makemigrations

  3. ./manage.py migrate --fake

ATAU, Anda dapat menulis migrasi dari semua ini

Ibrohim Ermatov
sumber
Saya harus menentukan nama aplikasi ./manage.py makemigrationsagar berfungsi, seperti:./manage.py makemigrations orders alerts
Salami
4

Saya mencoba perintah yang berbeda dan beberapa jawaban membantu saya. Hanya urutan ini dalam kasus saya yang memperbaiki kedua dependensi yang rusak dalam migrasi di MYAPP dan membersihkan semua migrasi sebelumnya mulai dari awal.

Sebelum melakukan ini, pastikan bahwa database sudah disinkronkan (misalnya, jangan menambahkan bidang Model baru di sini atau mengubah opsi Meta).

rm -Rf MYAPP/migrations/*
python manage.py makemigrations --empty MYAPP
python manage.py makemigrations
python manage.py migrate --fake MYAPP 0002

Di mana 0002 adalah nomor migrasi yang dikembalikan oleh perintah makemigrations terakhir.

Sekarang Anda dapat menjalankan makemigrations / migrate lagi secara normal karena migrasi 0002 disimpan tetapi tidak tercermin dalam database yang sudah disinkronkan.

chirale
sumber
Dari semua solusi yang disebutkan di atas, hanya ini yang berfungsi untuk saya tanpa kesalahan dan tanpa menghapus database.
Vivek Jha
3

Jika Anda tidak peduli dengan migrasi sebelumnya, bagaimana dengan hanya menghapus semua migrasi di direktori migrations /? Anda akan memulai urutan migrasi dari awal, menggunakan model Anda saat ini sebagai referensi seolah-olah Anda telah menulis seluruh model sekarang.

Jika Anda tidak cukup mempercayai saya untuk menghapusnya, cobalah untuk menyingkirkannya.

vokimon
sumber
Apa pentingnya mempertahankan migrasi lama? Pertanyaan saya menyentuh tanah ketika seseorang mencoba meningkatkan dari django 1.6 ke 1.8.
Jay Modi
Migrasi hanyalah rekam jejak dari perubahan yang Anda buat ke database. Saya telah menerima nasihat vokiman lebih dari sekali ketika rantai migrasi saya berhenti berfungsi.
Adam Starrh
1

Cara yang sederhana adalah

Buka setiap aplikasi dan hapus file migrasi.

Lalu pergi ke tabel django-migrtaions dalam database dan potong (hapus semua entri).

Setelah itu Anda dapat membuat migrasi sekali lagi.

sprksh
sumber
1
saat menghapus file migrasi, pastikan Anda tidak menghapus file init .
sprksh
Ini sangat membantu saya. Saya menghapus semua migrasi, menjatuhkan tabel dari DB sqlite saya, tetapi masih tidak dapat melakukan migrasi ... namun, setelah saya memulihkan file _init_ .py (doh) saya dapat melakukan migrasi lagi dan berlayar. @sprksh = Penyelamat!
twknab
0

cd ke direktori src cd /path/to/src

hapus direktori migrasi rm -rf your_app/migrations/

perhatikan bahwa ini harus dilakukan untuk setiap aplikasi secara terpisah

migrasi python3.3 manage.py migrate

jika Anda ingin memulai lagi python3.3 manage.py makemigrations your_app

Bebek karet
sumber
0

Jika Anda dalam mode pengembangan dan Anda hanya ingin mengatur ulang semuanya (database, migrasi, dll), saya menggunakan skrip ini berdasarkan jawaban Abdelhamid Ba. Ini akan menghapus tabel database (Postgres), menghapus semua file migrasi, menjalankan kembali migrasi dan memuat perlengkapan awal saya:

#!/usr/bin/env bash
echo "This will wipe out the database, delete migration files, make and apply migrations and load the intial fixtures."

while true; do
    read -p "Do you wish to continue?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo ">> Deleting old migrations"
find ../../src -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
psql -U db_user -d db_name -a -f ./reset-db.sql

echo ">> Running manage.py makemigrations and migrate"
./migrations.sh

echo ">> Loading initial fixtures"
./load_initial_fixtures.sh

echo ">> Done"

reset-db.sql file:

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

file migrasi.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py makemigrations
./manage.py migrate

file load_initial_fixtures.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py loaddata ~/path-to-fixture/fixture.json

Pastikan untuk mengubah jalur yang sesuai dengan aplikasi Anda. Saya pribadi memiliki skrip ini dalam folder bernama project_root / script / local, dan sumber django ada di project_root / src.

mrmuggles
sumber
0

Setelah menghapus setiap folder "migrasi" di aplikasi saya (secara manual), saya menjalankan:

./manage.py dbshell
delete from django_migrations;

Kemudian saya pikir saya bisa melakukannya ./manage.py makemigrationsuntuk meregenerasi semuanya. Namun, tidak ada perubahan yang terdeteksi. Saya kemudian mencoba menentukan satu aplikasi dalam satu waktu: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Namun, hal ini mengakibatkan ketergantungan melingkar yang tidak dapat diselesaikan.

Akhirnya, saya menjalankan satu perintah makemigrations yang menentukan SEMUA aplikasi saya (tanpa urutan tertentu):

./manage.py makemigrations foo bar bike orange banana etc

Kali ini, berhasil - dependensi melingkar diselesaikan secara otomatis (ini membuat file migrasi tambahan jika perlu).

Kemudian saya bisa lari ./manage.py migrate --fakedan kembali berbisnis.

shacker
sumber