Django 1.7'de geçişler nasıl basitleştirilir?


92

Güney için zaten benzer sorular var, ancak projeme Django 1.7 ile başladım ve Güney'i kullanmıyorum.

Geliştirme sırasında çok sayıda geçiş oluşturuldu, ancak yazılım henüz sunulmadı ve taşınması gereken bir veritabanı mevcut değil. Bu nedenle, geçişleri mevcut modelim orijinal modelmiş gibi sıfırlamak ve tüm veritabanlarını yeniden oluşturmak istiyorum.

Bunu yapmanın önerilen yolu nedir?

DÜZENLEME: Django 1.8'den itibaren, burada açıklanan sorunu az çok çözen squashmigrations adında yeni bir komut vardır .


Bir geçişi sıfırlamak ne demektir? Geri al?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Yanıtlar:


137

Bunu anladım. Bunu şimdi anladım ve bu iyi.

  • İlk olarak, geçişler tablosunu temizlemek için:

    ./manage.py migrate --fake <app-name> zero
    
  • app-name/migrations/Klasörü veya içeriği kaldırın .

  • Taşımaları yapın:

    ./manage.py makemigrations <app-name>
    
  • Son olarak, başka veritabanı değişiklikleri yapmadan geçişlerinizi düzenleyin:

    ./manage.py migrate --fake <app-name>
    

5
Bu iyi bir cevap. Yalnızca geçişleri silmek, hatalı geçişlerin verdiği zararı geri getirmez. Bu aslında listeyi temizler ve yeniden başlamanıza izin verir.
rogueleaderr

15
Biraz detaylandırırsanız, kabul edilen cevap bu olmalıdır.
tani-rokk

8
Tek satırlık harika bir cevap kardeşim, bunun ne yaptığı hakkında hiçbir fikrim yok
bischoffingston

13
Bu çizgi, ta ki göçleri tek tek tersine çevirir zero. Django geçiş sistemi <app-name> için artık yeni bir uygulama ve makemigrations <app-name>baştan başlayacak 0001. --faketabloların gerçekten değiştirilmesini engeller; bu, geçişlerin yalnızca tersine çevrilmiş olarak işaretlenmesi ve şemaya gerçekte uygulanmaması gerekir. (Tamlık adına küçük açıklamalar ekleyerek, @ tani-rokk, @Fabrizio)
Mir Nazim

17
manage.py migrate --fake <app-name> zerotaşıma tablosunu temizlemek için <uygulama adı> / migrations / klasörü veya içeriği kaldırın. Sonra manage.py makemigrations <app-name>ve sonunda yapın manage.py migrate --fake <app-name>. Bu, başka veritabanı değişiklikleri yapmadan geçişlerinizi düzenleyecektir.
doeke

36

Taşıma işlemlerinin Django 1.7 sürümünde, daha önce Güney'de bulunan sıfırlama işlevi, geçişlerinizi 'ezmek' için yeni işlevler lehine bırakılmıştır. Bunun, taşıma sayısını kontrol altında tutmanın iyi bir yolu olduğu varsayılıyor.

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

Hala gerçekten sıfırdan başlamak istiyorsanız, geçiş tablosunu boşaltarak ve daha sonra makemigrationstekrar çalıştıracağınız geçişleri kaldırarak hala yapabileceğinizi varsayıyorum .


2
Geçiş tablosunu boşaltmanın dışında "geçişleri nasıl kaldırırım"? Klasörün tamamını mı yoksa yalnızca 00X _ *. Py dosyalarını mı kaldırırım?
Kit Fisto

South ile, makemigrations yeniden çalıştırdığınızda yeniden oluşturulacak olan geçişler klasörünü kaldırabilirsiniz. Bunun Django 1.7 için de aynı şekilde çalıştığını varsayıyorum
tijs

4
Sadece bir not. Django 1.7'de, taşıma klasörünü dikkatlice silmezseniz, modeliniz başka birinin alt raise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algorithmatic

Özellikle ./manage.py squashmigrations myapp 0004, 0004uygulamanızda geçişten önce tüm geçişleri sıkıştıracaktır myapp. Bu, tek bir ezilmiş geçiş oluşturacaktır.
Bryce Guinta

22

Ben de aynı sorunu yaşadım. İşte benim çözümüm.

#!/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"

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


13
bu sadece geçişleri değil verileri de siler
ocaklar

2
.pyc

7

Bunun proje yapınız olduğunu varsayarsak,

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

Tüm taşıma dosyalarını silmek için, remove_migrations.py komut dosyasını yukarıda belirtilen yerden çalıştırabilirsiniz.

#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()

Ayrıntılı bir projeniz varsa manuel olarak silmek yorucu olabilir. Bu bana çok zaman kazandırdı. Taşıma dosyalarını silmek güvenlidir. Bunu hiçbir sorunla karşılaşmadan onuncu kez yaptım ... henüz.

Ancak taşıma klasörünü sildiğimde makemigrationsveya migrateklasörü benim için geri oluşturmadığımda. Komut dosyası, taşıma klasörünün __init__.pyyalnızca taşıma dosyalarını silerek yerinde kalmasını sağlar.


taşıma klasörlerini silebilir ve boş bir init .py ile yeniden oluşturabilirsiniz (örn. touch migrations/__init__.py)
hobs

6
  1. Dosyaları silin: delete_migrations.py (prj'nin kökünde):
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

VEYA, tüm bunlardan göç yazabilirsiniz


./manage.py makemigrationsÇalışmak için uygulama adlarını belirtmek zorunda kaldım , şöyle:./manage.py makemigrations orders alerts
Salami

4

Farklı komutlar deniyorum ve bazı cevaplar bana yardımcı oluyor. Yalnızca benim durumumdaki bu sıra, MYAPP'deki geçişlerdeki hem bozuk bağımlılıkları düzeltti hem de sıfırdan başlayarak tüm geçmiş geçişleri temizledi.

Bunu yapmadan önce veritabanının zaten senkronize edildiğinden emin olun (örn. Buraya yeni bir Model alanı eklemeyin veya Meta seçeneklerini değiştirmeyin).

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

0002, son makemigrations komutu tarafından döndürülen geçiş numarasıdır.

Artık makemigrations / migrate'ı normal şekilde çalıştırabilirsiniz çünkü taşıma 0002 depolanır ancak önceden senkronize edilmiş veritabanına yansıtılmaz.


Yukarıda belirtilen tüm çözümlerden sadece bu benim için bir aksaklık olmadan ve veritabanını silmeden çalıştı.
Vivek Jha

3

Önceki geçişleri önemsemiyorsanız, geçişler / dizinindeki tüm geçişleri kaldırmaya ne dersiniz? Tüm modeli şimdi yazmışsınız gibi mevcut modelinizi referans alarak geçiş sürecini sıfırdan başlatacaksınız.

Beni kaldıracağıma güvenmiyorsan, onun yerine onları uzaklaştırmayı dene.


Eski göçleri korumanın önemi nedir? Django 1.6'dan 1.8'e yükseltme yapılmaya çalışıldığında sorularım yerinden oynar.
Jay Modi

Taşıma işlemleri, veritabanında yaptığınız değişikliklerin bir geçmiş kaydıdır. Geçiş zincirim çalışmayı bıraktığında, vokiman'ın tavsiyesini birden fazla kez aldım.
Adam Starrh

1

Basit bir yol

Her uygulamaya gidin ve taşıma dosyalarını silin.

Daha sonra veritabanındaki django-migrtaions tablosuna gidin ve onu kesin (tüm girişleri silin).

Bundan sonra tekrar geçişler oluşturabilirsiniz.


1
taşıma dosyalarını silerken, init dosyalarını silmediğinizden emin olun .
sprksh

Bu bana gerçekten yardımcı oldu. Tüm geçişleri sildim, tabloları sqlite DB'mden kaldırdım, ancak yine de geçiş yapamadım ... ancak _init_ .py dosyalarını (doh) geri yükledikten sonra yeniden geçişler yapabildim ve seyir halindeydim. @sprksh = Cankurtaran!
twknab

0

cd'den src dizinine cd /path/to/src

taşıma dizinlerini sil rm -rf your_app/migrations/

bunun her uygulama için ayrı ayrı yapılması gerektiğini unutmayın

göç python3.3 manage.py migrate

yeniden başlamak istersen python3.3 manage.py makemigrations your_app


0

Geliştirme modundaysanız ve sadece her şeyi (veritabanı, geçişler, vb.) Sıfırlamak istiyorsanız, bu betiği Abdelhamid Ba'nın cevabına göre kullanıyorum. Bu, veritabanı tablolarını (Postgres) silecek, tüm geçiş dosyalarını silecek, geçişleri yeniden çalıştıracak ve ilk demirbaşlarımı yükleyecektir:

#!/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 dosyası:

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 $$;

migration.sh dosyası:

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

load_initial_fixtures.sh dosyası:

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

Yolları uygulamanıza karşılık gelecek şekilde değiştirdiğinizden emin olun. Şahsen bu betikleri project_root / script / local adlı bir klasörde ve django'nun kaynakları project_root / src'de var.


0

Uygulamamdaki her "taşıma" klasörünü sildikten sonra (manuel olarak) şunu çalıştırdım:

./manage.py dbshell
delete from django_migrations;

Sonra yapabileceğimi düşündüm ./manage.py makemigrations hepsini yeniden canlandırmak için . Ancak hiçbir değişiklik tespit edilmedi. Daha sonra her seferinde bir uygulama belirtmeyi denedim: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Ancak bu, çözülemeyen döngüsel bağımlılıklarla sonuçlandı.

Son olarak, TÜM uygulamalarımı belirten tek bir makemigrations komutu çalıştırdım (belirli bir sırayla değil):

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

Bu sefer işe yaradı - döngüsel bağımlılıklar otomatik olarak çözüldü (gerektiğinde ek geçiş dosyaları oluşturdu).

Sonra koşabildim ./manage.py migrate --fakeve işime geri döndüm.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.