0

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.

Alfonso_MA
  • 537
  • 5
  • 26
  • 1
    I have never worked with `MultiPolygonField` but the default you declared does not look like the "normal" input of the MultiPolygonField... As of my understanding you should open `python manage.py shell`, then import MultiPolygon, then create one MultiPolygon-Object. Most likely you can not create it with `MultiPolygon("SRID=3857;POINT(0.0 0.0)")`. Figure out what you have to input there to create that object. Then look up its __repr__ or __str__ function and take that as the default for your migration. – Tarquinius Feb 28 '23 at 10:08
  • Thanks for trying to help @Tarquinius. I can create MultiPolygonField with the following code: from django.contrib.gis.geos import GEOSGeometry then GEOSGeometry('SRID=4326;POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))'). I confirmed I can assign that to my MultiPolygonField and persist to the database without any issue. Unfortunately copying the string representation of that ('SRID=4326;POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))') to the prompt after I choose the option 1 leads me to the same error that I wrote in my first question. – Alfonso_MA Mar 02 '23 at 22:37
  • Actually, I confirmed that If I add I new MultiPolygonField (Instead of modifying, as I am trying) I can use an empty string '' as default value without any issue. That approach does not work in the case of modifying the field – Alfonso_MA Mar 02 '23 at 23:14
  • That does not make sense to me, since you are inserting a POINT to a MultiPolygonField. So I do not know why that assignment is working for you in the shell, because your input does not anywhere near like [this](https://docs.djangoproject.com/en/4.1/ref/contrib/gis/geos/#multipolygon). Also try to not specify the srid. It should be populated with a default then. Option 2 needs you to actually modify the already existing fields by hand via the shell. If you don't do it before `migrate` you get that error. – Tarquinius Mar 03 '23 at 08:33

1 Answers1

0

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.

Alfonso_MA
  • 537
  • 5
  • 26