Làm cách nào để đơn giản hóa việc di chuyển trong Django 1.7?


92

Đã có những câu hỏi tương tự cho South, nhưng tôi đã bắt đầu dự án của mình với Django 1.7 và không sử dụng South.

Trong quá trình phát triển, rất nhiều di chuyển đã được tạo ra, tuy nhiên phần mềm vẫn chưa được xóa và không có cơ sở dữ liệu nào phải được di chuyển. Do đó, tôi muốn đặt lại các di chuyển như thể mô hình hiện tại của tôi là mô hình ban đầu và tạo lại tất cả cơ sở dữ liệu.

Cách được khuyến nghị để làm điều đó là gì?

CHỈNH SỬA: Kể từ Django 1.8, có một lệnh mới tên là squashmigrations mà ít nhiều giải quyết được vấn đề được mô tả ở đây.


Đặt lại quá trình di chuyển có nghĩa là gì? Hủy bỏ nó?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Câu trả lời:


137

Tôi hiểu rồi. Tôi chỉ tìm ra điều này và nó là tốt.

  • Đầu tiên, để xóa bảng di chuyển:

    ./manage.py migrate --fake <app-name> zero
  • Xóa app-name/migrations/thư mục hoặc nội dung.

  • Thực hiện di chuyển:

    ./manage.py makemigrations <app-name>
  • Cuối cùng dọn dẹp quá trình di chuyển của bạn mà không thực hiện các thay đổi cơ sở dữ liệu khác:

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

5
Đây là một câu trả lời tốt. Chỉ xóa di chuyển không hoàn tác bất kỳ thiệt hại nào mà di chuyển bị lỗi đã gây ra. Điều này thực sự làm sạch phương tiện chặn và cho phép bạn bắt đầu lại.
rogueleaderr

15
Nếu bạn giải thích một chút, đây sẽ là câu trả lời được chấp nhận.
tani-rokk

8
Lớn một dòng câu trả lời bro, tôi không có ý tưởng gì này không
bischoffingston

13
Dòng này chỉ đơn giản là đảo ngược các lần di chuyển một, cho đến khi zero. Đối với hệ thống di chuyển Django, <app-name> hiện là một ứng dụng mới và makemigrations <app-name>sẽ bắt đầu từ đó 0001. --fakengăn các bảng thực sự bị sửa đổi, rằng quá trình di chuyển chỉ nên được đánh dấu là đã đảo ngược và không thực sự được áp dụng cho giản đồ. (Thêm những lời giải thích nhỏ vì lợi ích của sự đầy đủ, @ tani-rokk, @Fabrizio)
Mir Nazim

17
manage.py migrate --fake <app-name> zerođể xóa bảng di chuyển, sau đó xóa <app-name> / migrations / thư mục hoặc nội dung. Sau đó manage.py makemigrations <app-name>và cuối cùng làm manage.py migrate --fake <app-name>. Điều này sẽ dọn dẹp quá trình di chuyển của bạn mà không cần thực hiện các thay đổi cơ sở dữ liệu khác.
doeke

36

Trong phiên bản Django 1.7 của di chuyển, chức năng đặt lại từng có ở Nam đã bị loại bỏ để thay thế cho chức năng mới để 'xử lý' các di chuyển của bạn. Đây được cho là một cách tốt để kiểm soát số lượng di cư.

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

Nếu bạn vẫn muốn thực sự bắt đầu lại từ đầu, tôi cho rằng bạn vẫn có thể làm trống bảng di chuyển và xóa các di chuyển sau đó bạn sẽ chạy makemigrationslại.


2
Tôi làm cách nào để "xóa di chuyển" ngoài việc làm trống bảng di chuyển? Tôi sẽ xóa toàn bộ thư mục hay chỉ các tệp 00X _ *. Py?
Kit Fisto

với South, bạn có thể xóa thư mục di chuyển sẽ được tạo lại khi bạn chạy lại makemigrations. Tôi giả sử điều này hoạt động tương tự cho Django 1.7
tijs

4
Chỉ là một ghi chú. trong Django 1.7, nếu bạn không cẩn thận xóa thư mục di chuyển, nó có thể dẫn đến một ngoại lệ nếu mô hình của bạn là con của người khácraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algorithmatic

Cụ thể là ./manage.py squashmigrations myapp 0004sẽ xóa tất cả các lần di chuyển trước khi di chuyển 0004trong ứng dụng của bạn myapp. Điều này sẽ tạo ra một lần di chuyển bị bóp nghẹt.
Bryce Guinta

22

tôi chỉ có cùng một vấn đề. Đây là cách giải quyết của tôi.

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

Các findlệnh: http://unixhelp.ed.ac.uk/CGI/man-cgi?find


13
điều này sẽ xóa dữ liệu, không chỉ di chuyển
hobs

2
bạn nên xóa file pyc quá
shalbafzadeh

7

Giả sử đây là cấu trúc dự án của bạn,

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

bạn có thể chạy script remove_migrations.py từ nơi được chỉ định ở trên để xóa tất cả các tệp di chuyển.

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

Việc xóa thủ công có thể gây mệt mỏi nếu bạn có một dự án phức tạp. Điều này đã tiết kiệm cho tôi rất nhiều thời gian. Xóa tệp di chuyển là an toàn. Tôi đã làm điều này số lần thứ mười mười hai mà không gặp phải bất kỳ vấn đề nào ...

Tuy nhiên, khi tôi xóa thư mục di chuyển makemigrationshoặc migratekhông tạo lại thư mục cho tôi. Tập lệnh đảm bảo rằng thư mục di chuyển __init__.pyvẫn được giữ nguyên, chỉ xóa các tệp di chuyển.


bạn chỉ có thể xóa các thư mục di cư và tái tạo chúng với một sản phẩm nào init py (ví dụ touch migrations/__init__.py)
Hobs

6
  1. Xóa tệp: delete_migrations.py (trong thư mục gốc của 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 di chuyển --fake

HOẶC, bạn có thể viết di chuyển từ tất cả


Tôi phải ghi rõ tên ứng dụng cho ./manage.py makemigrationscông việc, thích vậy:./manage.py makemigrations orders alerts
Salami

4

Tôi thử các lệnh khác nhau và một số câu trả lời giúp tôi. Chỉ trình tự này trong trường hợp của tôi đã sửa cả hai lỗi phụ thuộc bị hỏng trong quá trình di chuyển trong MYAPP và xóa tất cả các lần di chuyển trước đây bắt đầu từ đầu.

Trước khi thực hiện việc này, hãy đảm bảo rằng cơ sở dữ liệu đã được đồng bộ hóa (ví dụ: không thêm trường Model mới vào đây hoặc thay đổi các tùy chọn Meta).

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

Trong đó 0002 là số di chuyển được trả về bởi lệnh makemigrations cuối cùng.

Bây giờ bạn có thể chạy makemigrations / di chuyển lại bình thường vì chuyển đổi 0002 được lưu trữ nhưng không được phản ánh trong cơ sở dữ liệu đã được đồng bộ hóa.


Trong số tất cả các giải pháp được đề cập ở trên, chỉ có giải pháp này hoạt động với tôi mà không gặp trục trặc và không xóa cơ sở dữ liệu.
Vivek Jha

3

Nếu bạn không quan tâm đến các lần di chuyển trước, bạn chỉ cần xóa tất cả các lần di chuyển trong thư mục migrations / thì sao? bạn sẽ bắt đầu trình tự di chuyển từ đầu, lấy mô hình hiện tại của bạn làm tham chiếu như thể bạn đã viết toàn bộ mô hình ngay bây giờ.

Nếu bạn không tin tưởng tôi thì bạn nên xóa, thay vào đó hãy thử chuyển chúng đi.


Ý nghĩa của việc duy trì các cuộc di cư cũ là gì? Câu hỏi của tôi chạm đến cơ sở khi một người cố gắng nâng cấp từ django 1.6 lên 1.8.
Jay Modi,

Di chuyển chỉ đơn giản là một bản ghi theo dõi những thay đổi bạn đã thực hiện đối với cơ sở dữ liệu. Tôi đã thực hiện lời khuyên của vokiman nhiều lần khi chuỗi di chuyển của tôi ngừng hoạt động.
Adam Starrh

1

Một cách đơn giản là

Đi tới mọi ứng dụng và xóa các tệp di chuyển.

Sau đó, chuyển đến bảng django-migrtaions trong cơ sở dữ liệu và cắt bớt nó (xóa tất cả các mục nhập).

Sau đó, bạn có thể tạo di chuyển một lần nữa.


1
trong khi xóa các tệp di chuyển, hãy đảm bảo rằng bạn không xóa các tệp init .
sprksh

Điều này thực sự đã giúp tôi. Tôi đã xóa tất cả các lần di chuyển, xóa các bảng khỏi DB sqlite của mình, nhưng vẫn không thể thay đổi ... tuy nhiên, sau khi khôi phục các tệp _init_ .py (doh), tôi đã có thể thay đổi lại và bắt đầu hành trình. @sprksh = Cứu sinh!
twknab

0

cd đến thư mục src cd /path/to/src

xóa thư mục di chuyển rm -rf your_app/migrations/

lưu ý rằng điều này nên được thực hiện cho từng ứng dụng riêng biệt

di cư python3.3 manage.py migrate

nếu bạn muốn bắt đầu lại python3.3 manage.py makemigrations your_app


0

Nếu bạn đang ở chế độ phát triển và bạn chỉ muốn đặt lại mọi thứ (cơ sở dữ liệu, di chuyển, v.v.), tôi sử dụng tập lệnh này dựa trên câu trả lời của Abdelhamid Ba. Thao tác này sẽ xóa các bảng của cơ sở dữ liệu (Postgres), xóa tất cả các tệp di chuyển, chạy lại quá trình di chuyển và tải các đồ đạc ban đầu của tôi:

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

tệp reset-db.sql:

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

tệpigration.sh:

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

tệp load_initial_fixtures.sh:

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

Chỉ cần đảm bảo thay đổi các đường dẫn để tương ứng với ứng dụng của bạn. Cá nhân tôi có các tập lệnh này trong một thư mục có tên là project_root / script / local và các nguồn của django nằm trong project_root / src.


0

Sau khi xóa từng thư mục "di chuyển" trong ứng dụng của mình (theo cách thủ công), tôi đã chạy:

./manage.py dbshell
delete from django_migrations;

Sau đó, tôi nghĩ tôi có thể làm gì ./manage.py makemigrationsđể tái tạo tất cả chúng. Tuy nhiên, không có thay đổi nào được phát hiện. Sau đó, tôi đã thử chỉ định một ứng dụng tại một thời điểm: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Tuy nhiên, điều này dẫn đến các phụ thuộc vòng tròn không thể được giải quyết.

Cuối cùng, tôi đã chạy một lệnh makemigrations duy nhất chỉ định TẤT CẢ các ứng dụng của tôi (không theo thứ tự cụ thể):

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

Lần này, nó hoạt động - các phụ thuộc vòng tròn đã được tự động giải quyết (nó tạo ra các tệp di chuyển bổ sung nếu cần).

Sau đó, tôi đã có thể điều hành ./manage.py migrate --fakevà trở lại kinh doanh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.