Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
fdc2cc94
Kaydet (Commit)
fdc2cc94
authored
Ock 10, 2015
tarafından
Markus Holtermann
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #24110 -- Rewrote migration unapply to preserve intermediate states
üst
d89019a8
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
45 additions
and
26 deletions
+45
-26
migration.py
django/db/migrations/migration.py
+26
-15
1.7.3.txt
docs/releases/1.7.3.txt
+2
-0
test_operations.py
tests/migrations/test_operations.py
+17
-11
No files found.
django/db/migrations/migration.py
Dosyayı görüntüle @
fdc2cc94
...
@@ -115,28 +115,39 @@ class Migration(object):
...
@@ -115,28 +115,39 @@ class Migration(object):
Takes a project_state representing all migrations prior to this one
Takes a project_state representing all migrations prior to this one
and a schema_editor for a live database and applies the migration
and a schema_editor for a live database and applies the migration
in a reverse order.
in a reverse order.
The backwards migration process consists of two phases:
1. The intermediate states from right before the first until right
after the last opertion inside this migration are preserved.
2. The operations are applied in reverse order using the states
recorded in step 1.
"""
"""
#
We need to pre-calculate the stack of project states
#
Construct all the intermediate states we need for a reverse migration
to_run
=
[]
to_run
=
[]
new_state
=
project_state
# Phase 1
for
operation
in
self
.
operations
:
for
operation
in
self
.
operations
:
# If this operation cannot be represented as SQL, place a comment
# there instead
if
collect_sql
and
not
operation
.
reduces_to_sql
:
schema_editor
.
collected_sql
.
append
(
"--"
)
schema_editor
.
collected_sql
.
append
(
"-- MIGRATION NOW PERFORMS OPERATION THAT CANNOT BE "
"WRITTEN AS SQL:"
)
schema_editor
.
collected_sql
.
append
(
"--
%
s"
%
operation
.
describe
())
schema_editor
.
collected_sql
.
append
(
"--"
)
continue
# If it's irreversible, error out
# If it's irreversible, error out
if
not
operation
.
reversible
:
if
not
operation
.
reversible
:
raise
Migration
.
IrreversibleError
(
"Operation
%
s in
%
s is not reversible"
%
(
operation
,
self
))
raise
Migration
.
IrreversibleError
(
"Operation
%
s in
%
s is not reversible"
%
(
operation
,
self
))
old_state
=
project_state
.
clone
()
# Preserve new state from previous run to not tamper the same state
operation
.
state_forwards
(
self
.
app_label
,
project_state
)
# over all operations
to_run
.
append
((
operation
,
old_state
,
project_state
))
new_state
=
new_state
.
clone
()
# Now run them in reverse
old_state
=
new_state
.
clone
()
to_run
.
reverse
()
operation
.
state_forwards
(
self
.
app_label
,
new_state
)
to_run
.
insert
(
0
,
(
operation
,
old_state
,
new_state
))
# Phase 2
for
operation
,
to_state
,
from_state
in
to_run
:
for
operation
,
to_state
,
from_state
in
to_run
:
if
collect_sql
:
if
not
operation
.
reduces_to_sql
:
schema_editor
.
collected_sql
.
append
(
"--"
)
schema_editor
.
collected_sql
.
append
(
"-- MIGRATION NOW PERFORMS OPERATION THAT CANNOT BE "
"WRITTEN AS SQL:"
)
schema_editor
.
collected_sql
.
append
(
"--
%
s"
%
operation
.
describe
())
schema_editor
.
collected_sql
.
append
(
"--"
)
continue
if
not
schema_editor
.
connection
.
features
.
can_rollback_ddl
and
operation
.
atomic
:
if
not
schema_editor
.
connection
.
features
.
can_rollback_ddl
and
operation
.
atomic
:
# We're forcing a transaction on a non-transactional-DDL backend
# We're forcing a transaction on a non-transactional-DDL backend
with
atomic
(
schema_editor
.
connection
.
alias
):
with
atomic
(
schema_editor
.
connection
.
alias
):
...
...
docs/releases/1.7.3.txt
Dosyayı görüntüle @
fdc2cc94
...
@@ -26,3 +26,5 @@ Bugfixes
...
@@ -26,3 +26,5 @@ Bugfixes
(:ticket:`24097`).
(:ticket:`24097`).
* Added correct formats for Greek (``el``) (:ticket:`23967`).
* Added correct formats for Greek (``el``) (:ticket:`23967`).
* Fixed a migration crash when unapplying a migration (:ticket:`24110`).
tests/migrations/test_operations.py
Dosyayı görüntüle @
fdc2cc94
...
@@ -465,27 +465,33 @@ class OperationTests(OperationTestBase):
...
@@ -465,27 +465,33 @@ class OperationTests(OperationTestBase):
# Test the state alteration
# Test the state alteration
operation
=
migrations
.
RenameModel
(
"Pony"
,
"Horse"
)
operation
=
migrations
.
RenameModel
(
"Pony"
,
"Horse"
)
self
.
assertEqual
(
operation
.
describe
(),
"Rename model Pony to Horse"
)
self
.
assertEqual
(
operation
.
describe
(),
"Rename model Pony to Horse"
)
new_state
=
project_state
.
clone
()
# Test initial state and database
operation
.
state_forwards
(
"test_rnmo"
,
new_state
)
self
.
assertIn
((
"test_rnmo"
,
"pony"
),
project_state
.
models
)
self
.
assertNotIn
((
"test_rnmo"
,
"pony"
),
new_state
.
models
)
self
.
assertNotIn
((
"test_rnmo"
,
"horse"
),
project_state
.
models
)
self
.
assertIn
((
"test_rnmo"
,
"horse"
),
new_state
.
models
)
# Remember, RenameModel also repoints all incoming FKs and M2Ms
self
.
assertEqual
(
"test_rnmo.Horse"
,
new_state
.
models
[
"test_rnmo"
,
"rider"
]
.
fields
[
1
][
1
]
.
rel
.
to
)
# Test the database alteration
self
.
assertTableExists
(
"test_rnmo_pony"
)
self
.
assertTableExists
(
"test_rnmo_pony"
)
self
.
assertTableNotExists
(
"test_rnmo_horse"
)
self
.
assertTableNotExists
(
"test_rnmo_horse"
)
if
connection
.
features
.
supports_foreign_keys
:
if
connection
.
features
.
supports_foreign_keys
:
self
.
assertFKExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_pony"
,
"id"
))
self
.
assertFKExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_pony"
,
"id"
))
self
.
assertFKNotExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_horse"
,
"id"
))
self
.
assertFKNotExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_horse"
,
"id"
))
with
connection
.
schema_editor
()
as
editor
:
# Migrate forwards
operation
.
database_forwards
(
"test_rnmo"
,
editor
,
project_state
,
new_state
)
new_state
=
project_state
.
clone
()
new_state
=
self
.
apply_operations
(
"test_rnmo"
,
new_state
,
[
operation
])
# Test new state and database
self
.
assertNotIn
((
"test_rnmo"
,
"pony"
),
new_state
.
models
)
self
.
assertIn
((
"test_rnmo"
,
"horse"
),
new_state
.
models
)
# RenameModel also repoints all incoming FKs and M2Ms
self
.
assertEqual
(
"test_rnmo.Horse"
,
new_state
.
models
[
"test_rnmo"
,
"rider"
]
.
fields
[
1
][
1
]
.
rel
.
to
)
self
.
assertTableNotExists
(
"test_rnmo_pony"
)
self
.
assertTableNotExists
(
"test_rnmo_pony"
)
self
.
assertTableExists
(
"test_rnmo_horse"
)
self
.
assertTableExists
(
"test_rnmo_horse"
)
if
connection
.
features
.
supports_foreign_keys
:
if
connection
.
features
.
supports_foreign_keys
:
self
.
assertFKNotExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_pony"
,
"id"
))
self
.
assertFKNotExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_pony"
,
"id"
))
self
.
assertFKExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_horse"
,
"id"
))
self
.
assertFKExists
(
"test_rnmo_rider"
,
[
"pony_id"
],
(
"test_rnmo_horse"
,
"id"
))
# And test reversal
# Migrate backwards
self
.
unapply_operations
(
"test_rnmo"
,
project_state
,
[
operation
])
original_state
=
self
.
unapply_operations
(
"test_rnmo"
,
project_state
,
[
operation
])
# Test original state and database
self
.
assertIn
((
"test_rnmo"
,
"pony"
),
original_state
.
models
)
self
.
assertNotIn
((
"test_rnmo"
,
"horse"
),
original_state
.
models
)
self
.
assertEqual
(
"Pony"
,
original_state
.
models
[
"test_rnmo"
,
"rider"
]
.
fields
[
1
][
1
]
.
rel
.
to
)
self
.
assertTableExists
(
"test_rnmo_pony"
)
self
.
assertTableExists
(
"test_rnmo_pony"
)
self
.
assertTableNotExists
(
"test_rnmo_horse"
)
self
.
assertTableNotExists
(
"test_rnmo_horse"
)
if
connection
.
features
.
supports_foreign_keys
:
if
connection
.
features
.
supports_foreign_keys
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment