$
scp
elspeth@superlists.ottg.eu:\
/home/elspeth/sites/superlists.ottg.eu/database/db.sqlite3 .
$
mv ../database/db.sqlite3 ../database/db.sqlite3.bak
$
mv db.sqlite3 ../database/db.sqlite3
Confirming the Error
We now have a local database that has not been migrated, and that contains some prob‐
lematic data. We should see an error if we try to run
migrate
:
$
python3 manage.py migrate --migrate
python3 manage.py migrate
Operations to perform:
[...]
Running migrations:
[...]
Applying lists.0005_list_item_unique_together...Traceback (most recent call
last):
[...]
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: columns list_id, text are not unique
Inserting a Data Migration
Data migrationsare a special type of migration that modifies data in the database rather
than changing the schema. We need to create one that will run before we apply the
integrity constraint, to preventively remove any duplicates. Here’s how we can do that:
$
git rm lists/migrations/0005_list_item_unique_together.py
$
python3 manage.py makemigrations lists --empty
Migrations for 'lists':
0005_auto_20140414_2325.py:
$
mv lists/migrations/0005_
lists/migrations/0005_remove_duplicates.py*
Check out
the Django docs on data migrationsfor more info, but here’s how we add
some instructions to change existing data:
lists/migrations/0005_remove_duplicates.py.
# encoding: utf8
from
django.db
import
models
,
migrations
def
find_dupes
(
apps
,
schema_editor
):
List
=
apps
.
get_model
(
"lists"
,
"List"
)
for
list_
in
List
.
objects
.
all
():
items
=
list_
.
item_set
.
all
()
texts
=
set
()
for
ix
,
item
in
enumerate
(
items
):
if
item
.
text
in
texts
:
item
.
text
=
'{} ({})'
.
format
(
item
.
text
,
ix
)
item
.
save
()
texts
.
add
(
item
.
text
)
Inserting a Data Migration
|
429