简体   繁体   中英

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM