Django: Convert CharField to TextField with data intact
Is there a way to change a CharField to a TextField and keep the data from this column intact?
Right now I have the following:
class TestLog(models.Model):
failed_reqs = models.CharField(max_length=DB_MAX_CHAR_LENGTH, blank=True)
passed_reqs = models.CharField(max_length=DB_MAX_CHAR_LENGTH, blank=True)
But the DB_MAX_CHAR_LENGTH is 500开发者_如何转开发, and as it turns out this field can sometimes exceed that, so I want to go to:
class TestLog(models.Model):
failed_reqs = models.TextField(blank=True)
passed_reqs = models.TextField(blank=True)
How do I do this and keep my data intact on the production database?
Djangobook details how to add and remove fields, and I've tried using South to do this as well, but South gave me an error, and looking at the output from before the error it appears as though South is dropping and recreating the DB. Is this what south's data migrations is all about?
This is solved with django migrations (1.7+). If you change the type from CharField to TextField, the migration produced is AlterField, which does the right thing.
Assuming that you have access to the database, as you mentioned the way Django talks about adding and removing columns, I've listed methods for both Postgresql and MySQL since you didn't mention what you were using.
Postgresql:
BEGIN;
ALTER TABLE "TestLog"
ALTER COLUMN "failed_reqs" TYPE TEXT,
ALTER COLUMN "passed_reqs" TYPE TEXT;
COMMIT;
MySQL:
BEGIN;
ALTER TABLE TestLog
MODIFY failed_reqs TEXT NULL,
MODIFY passed_reqs TEXT NULL;
COMMIT;
I would highly recommend backing up your database before doing these changes.
Off hand, I would continue to look into a South approach. This is the workflow that I would try:
1) South schema migration to create two new TextField fields called something like "failed_reqs_txt" and "passed_reqs_txt".
2) Create a data migration to migrate the data from the old fields to the new fields
3) Create a schema migration to delete the original "failed_reqs" and "passed_reqs" fields.
---- if you need the fields to be the same name as the original, I would then proceed to:
4) Create a schema migration to add "failed_reqs", and "passed_reqs" as TextFields
5) Create a data migration to migrate from the "failed_reqs_txt" and "passed_reqs_txt" to the "failed_reqs", and "passed_reqs" fields.
6) Create a schema migration to drop the "failed_reqs_txt" and "passed_reqs_txt" fields.
Though this is a lot of migrations, it breaks up each change into atomic migrations. I'd try this first. I'm not sure why South would be dropping and recreating the db. Did you run the convert_to_south option when adding south to your project? I think this fakes a migration and lets south know that it's working with an existing project and not a new one.
As an alternative, you could do some direct ALTERS to the database to alter the column type and then update the model.py from CharField to TextField. Postgres, supposedly supports implicitly changing data types this way. (See Section 5.5.6.) I'm not sure about mysql, but I think it works the same. (CharField to TextFiled should be a compatible conversion)
Regardless, I'd backup my data before making any such changes. Hope this helps.
精彩评论