Tôi đã thực hiện một di chuyển đã thêm một bảng mới và muốn hoàn nguyên nó và xóa di chuyển mà không tạo ra một di chuyển mới.
Tôi phải làm nó như thế nào? Có một lệnh để hoàn nguyên di chuyển cuối cùng và sau đó tôi chỉ có thể xóa tệp di chuyển?
Tôi đã thực hiện một di chuyển đã thêm một bảng mới và muốn hoàn nguyên nó và xóa di chuyển mà không tạo ra một di chuyển mới.
Tôi phải làm nó như thế nào? Có một lệnh để hoàn nguyên di chuyển cuối cùng và sau đó tôi chỉ có thể xóa tệp di chuyển?
Câu trả lời:
Bạn có thể hoàn nguyên bằng cách di chuyển đến lần di chuyển trước.
Ví dụ: nếu hai lần di chuyển cuối cùng của bạn là:
0010_previous_migration
0011_migration_to_revert
Sau đó, bạn sẽ làm:
./manage.py migrate my_app 0010_previous_migration
Sau đó bạn có thể xóa di chuyển 0011_migration_to_revert
.
Nếu bạn đang sử dụng Django 1.8+, bạn có thể hiển thị tên của tất cả các lần di chuyển với
./manage.py showmigrations my_app
Để đảo ngược tất cả các lần di chuyển cho một ứng dụng, bạn có thể chạy:
./manage.py migrate my_app zero
'0010_previous_migration'
, tôi không biết tại sao bạn sẽ thấy hành vi đó.
Câu trả lời của Alasdair bao gồm những điều cơ bản
./manage.py showmigrations
migrate
sử dụng tên ứng dụng và tên di chuyểnNhưng cần phải chỉ ra rằng không phải tất cả các cuộc di cư đều có thể đảo ngược. Điều này xảy ra nếu Django không có quy tắc để thực hiện đảo ngược. Đối với hầu hết các thay đổi mà bạn tự động thực hiện di chuyển theo ./manage.py makemigrations
, việc đảo ngược sẽ có thể. Tuy nhiên, các tập lệnh tùy chỉnh sẽ cần phải có cả văn bản chuyển tiếp và ngược lại, như được mô tả trong ví dụ ở đây:
https://docs.djangoproject.com/en/1.9/ref/migration-operations/
Nếu bạn đã có một RunPython
hoạt động, thì có lẽ bạn chỉ muốn sao lưu di chuyển mà không viết một kịch bản đảo ngược logic chặt chẽ. Việc hack nhanh vào ví dụ từ các tài liệu (liên kết ở trên) cho phép điều này, khiến cơ sở dữ liệu ở trạng thái giống như sau khi di chuyển được áp dụng, ngay cả sau khi đảo ngược nó.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
]
Điều này hoạt động cho Django 1.8, 1.9
Cập nhật: Một cách tốt hơn để viết này sẽ là thay thế lambda apps, schema_editor: None
bằng migrations.RunPython.noop
trong đoạn trích ở trên. Cả hai đều có chức năng giống nhau. (ghi nhận ý kiến)
RunPython.noop
thay vì lambda nội tuyến hoặc tương đương: docs.djangoproject.com/en/1.8/ref/migration-operations/ory
migrations.RunPython(forwards_func, migrations.RunPython.noop)
. Cần kiểm tra chức năng đó. Điều đó sẽ được thêm vào như một câu trả lời hoặc chỉnh sửa đôi khi.
Đây là giải pháp của tôi, vì giải pháp trên không thực sự bao gồm trường hợp sử dụng, khi bạn sử dụng RunPython
.
Bạn có thể truy cập bảng thông qua ORM với
from django.db.migrations.recorder import MigrationRecorder
>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})
Vì vậy, bạn có thể truy vấn các bảng và xóa các mục có liên quan đến bạn. Bằng cách này bạn có thể sửa đổi chi tiết. Với RynPython
việc di chuyển, bạn cũng cần chăm sóc dữ liệu đã được thêm / thay đổi / xóa. Ví dụ trên chỉ hiển thị, cách bạn truy cập bảng thông qua Djang ORM.
django.db.utils.ProgrammingError: relation "<relation name>" already exists
vậy vì vậy tôi đã gửi một migrate --fake
lỗi sai, vì vậy tôi đã cố gắng quay lại, sau đó tôi đã nhận được psycopg2.ProgrammingError: relation "<other <relation name>" does not exist
THANKS
Một điều khác mà bạn có thể làm là xóa bảng được tạo thủ công.
Cùng với đó, bạn sẽ phải xóa tệp di chuyển cụ thể đó. Ngoài ra, bạn sẽ phải xóa mục cụ thể đó trong bảng di chuyển django (có thể là mục cuối cùng trong trường hợp của bạn) có liên quan đến việc di chuyển cụ thể đó.
Không xóa tệp di chuyển cho đến sau khi đảo ngược. Tôi đã mắc lỗi này và không có tệp di chuyển, cơ sở dữ liệu không biết phải xóa những gì.
python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}
Xóa tệp di chuyển. Khi di chuyển mong muốn trong mô hình của bạn ...
python manage.py makemigrations
python manage.py migrate
Tôi đã làm điều này trong 1.9.1 (để xóa di chuyển cuối cùng hoặc mới nhất được tạo):
rm <appname>/migrations/<migration #>*
thí dụ: rm myapp/migrations/0011*
đăng nhập vào cơ sở dữ liệu và chạy SQL này (postgres trong ví dụ này)
delete from django_migrations where name like '0011%';
Sau đó tôi đã có thể tạo các di chuyển mới bắt đầu bằng số di chuyển mà tôi vừa xóa (trong trường hợp này là 11).
Câu trả lời này dành cho các trường hợp tương tự nếu câu trả lời hàng đầu của Alasdair không có ích . (Ví dụ: nếu di chuyển không mong muốn được tạo lại một lần nữa với mỗi lần di chuyển mới hoặc nếu di chuyển lớn hơn không thể được hoàn nguyên hoặc bảng đã bị xóa theo cách thủ công.)
... Xóa di chuyển mà không tạo di chuyển mới?
TL; DR : Bạn có thể xóa một vài lần di chuyển được hoàn nguyên (nhầm lẫn) cuối cùng và thực hiện một lần di chuyển mới sau khi sửa mô hình . Bạn cũng có thể sử dụng các phương thức khác để cấu hình nó để không tạo bảng bằng cách di chuyển lệnh. Di chuyển cuối cùng phải được tạo để nó phù hợp với các mô hình hiện tại .
Các trường hợp tại sao mọi người không muốn tạo bảng cho Mô hình phải tồn tại:
A) Không có bảng như vậy tồn tại trong cơ sở dữ liệu không có máy và không có điều kiện
class Meta: abstract = True
B) Bảng được tạo hiếm khi, bằng cách khác hoặc thủ công theo cách đặc biệt.
class Meta: managed = False
C) Bảng chỉ được sử dụng trên một số máy (ví dụ như trong quá trình phát triển).
class Meta: managed = some_switch
.D) Dự án sử dụng nhiều cơ sở dữ liệu trongsettings.DATABASES
allow_migrate
để phân biệt cơ sở dữ liệu nơi bảng sẽ được tạo và nơi không.Di chuyển được tạo trong tất cả các trường hợp A), B), C), D) với Django 1.9+ (và chỉ trong các trường hợp B, C, D với Django 1.8), nhưng chỉ áp dụng cho cơ sở dữ liệu trong các trường hợp thích hợp hoặc có thể không bao giờ Yêu cầu như vậy. Di chuyển là cần thiết để chạy thử nghiệm kể từ Django 1.8. Trạng thái hiện tại hoàn toàn có liên quan được ghi lại bằng cách di chuyển ngay cả đối với các mô hình có Managed = false trong Django 1.9+ để có thể tạo ForeignKey giữa các mô hình được quản lý / không được quản lý hoặc để có thể tạo mô hình được quản lý = True sau này. (Câu hỏi này đã được viết tại thời điểm Django 1.8. Mọi thứ ở đây phải hợp lệ cho các phiên bản từ 1.8 đến 2.2 hiện tại.)
Nếu lần di chuyển cuối cùng là (không) dễ dàng hoàn nguyên thì có thể thận trọng (sau khi sao lưu cơ sở dữ liệu) thực hiện hoàn nguyên giả ./manage.py migrate --fake my_app 0010_previous_migration
, xóa bảng theo cách thủ công.
Nếu cần, hãy tạo một di chuyển cố định từ mô hình cố định và áp dụng nó mà không thay đổi cấu trúc cơ sở dữ liệu ./manage.py migrate --fake my_app 0011_fixed_migration
.
Nếu bạn đang phải đối mặt với rắc rối trong khi hoàn nguyên việc di chuyển và bằng cách nào đó đã làm hỏng nó, bạn có thể thực hiện fake
di chuyển.
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
Đối với phiên bản django <1.7, điều này sẽ tạo mục trong south_migrationhistory
bảng, bạn cần xóa mục đó.
Bây giờ bạn sẽ có thể hoàn nguyên việc di chuyển trở lại một cách dễ dàng.
Tái bút: Tôi đã bị mắc kẹt trong nhiều thời gian và thực hiện di chuyển giả và sau đó quay trở lại đã giúp tôi ra ngoài.