I'm changing a field from CharField
to IntegerField
. The field name remains the same. The newly created field will be based off the old field. For example, if the old field was "L", it would have the number "1" instead. How can I accomplish this in the forwards()
function?
makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.
The correct way to do it would be to break this into three migrations:
IntegerField
field.CharField
to the IntegerField
CharField
.A fourth one might be required if you want your newly added IntegerField
to have the same name as the to-be-removed CharField
.
Given a project state where the IntegerField
is not yet added to you model file you should proceed by following these steps:
IntegerField
to you model.datamigration
) for the application containing your model. In the forwards()
method of the newly created DataMigration
class write down your logic to convert your data. Try to use the update
manager method instead of iterating overt all your database row if possible. If you declare your conversion logic using a dict
(say {'L': 1, ...}
) it should be pretty easy to also implement backwards()
at this time, given the operation is invertible. It's also a good exercise to make sure you've not overlooked an edged case in forwards()
-- it helped me quite a few times in the past.CharField
from your model.DROP
the now unused column.The fact that you broke this operation into three migrations instead of writing down your whole logic in a blank template have a couple advantages:
ADD
/DROP
logic have been automatically generated by South and you don't have to worry about introducing a typo in a database column.DataMigration.backwards()
for the conversion step you should be able to completely reverse the whole operation. This can be handy for testing purpose, if you need to rollback to a previous revision of your code and as safe net when updating a production code base.forwards()
method in this case) and an exception was raised during the data migration step (say a KeyError
because of an unhandled value in your conversion dict
). If you're using a ORDBMS
that doesn't support transactional schema alteration you wouldn't be able to re-run you migration immediately after fixing the data-migration part, you'd have to manually drop the newly added IntegerField
column yourself. Again, that's the kind of thing you don't want to deal with when migrating a production database.for the same situation me followed just 3 steps .
1) changed file type from CharField to IntegerField,
2) ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (col_name::integer); or
ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (trim(col_name)::integer); # in case if you having whitespace in your Char or Text field. and if you having data's in your table, which should be string of integer.
3) Now apply migration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With