Django 4: How to modify MultiPolygonField from nullable to not-null

204 views Asked by At

I am trying to convert my MultiPolygonField field from this:

multipolygon = MultiPolygonField(null=True)

to this:

multipolygon = MultiPolygonField(null=False)

It looks simple, so I execute "makemigrations" and I get the usual message warning that the database needs something to populate existing rows (I confirmed that there is no row in my database with that field being null):

Whether I choose option 1:

  1. Provide a one-off default now (will be set on all existing rows with a null value for this column)

And set the following as default:

'SRID=3857;POINT(0.0 0.0)'

or option 2:

  1. Ignore for now. Existing rows that contain NULL values will have to be handled manually, for example with a RunPython or RunSQL operation

I get the following error when I execute "migrate":

ValueError: Cannot alter field borders.Border.multipolygon into borders.Border.multipolygon - they do not properly define db_type (are you using a badly-written custom field?)

I have been able to make that same change with other simpler field types without any issue. How to do this with MultiPolygonFields? I am using Django 4 and sqlite 3.31, in case that matters.

1

There are 1 answers

0
Alfonso_MA On BEST ANSWER

This is how I finally "solved" the issue (not exactly solved, but I found a longer way to get the same results):

I divided the migration in 6 steps:

  1. I created a new field "multipolygon_new"
  2. I copied data from my initial field "multipolygon" to the new one I just created "multipolygon_new"
  3. I deleted my initial field, "multipolygon"
  4. I created "multipolygon" again, but being not-null
  5. I copied data from "multipolygon_new" to ""multipolygon"
  6. I deleted "multipolygon_new"

For steps 2 and 5 used the following command to create a custom migration:

python manage.py makemigrations --empty yourappname

and then I modified the migration file to execute my custom copy query:

migrations.RunSQL(
    sql=[("UPDATE mytable ......", ],
)

for the other steps I used the usual makemigrations command.