Opened 6 years ago
Last modified 5 years ago
#30489 closed Bug
Django RasterField deserialization bug with pixeltype flags — at Version 1
Reported by: | Ivor Bosloper | Owned by: | nobody |
---|---|---|---|
Component: | GIS | Version: | dev |
Severity: | Normal | Keywords: | RasterField |
Cc: | Hasan Ramezani | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
After inserting some raster data with raster2pgsql into a Django model table with a RasterField column, I get a list index out of range
when querying the table with a Django Queryset.
... File "django/contrib/gis/db/models/fields.py" in from_db_value 360. return connection.ops.parse_raster(value) File "django/contrib/gis/db/backends/postgis/operations.py" in parse_raster 369. return from_pgraster(value) File "django/contrib/gis/db/backends/postgis/pgraster.py" in from_pgraster 57. pixeltype = POSTGIS_TO_GDAL[pixeltype]
It turns out the pixeltype
value used is 39 while the POSTGIS_TO_GDAL
list is only 16 elements long. The database field contains valid data but can not be deserialized with Django.
Steps for reproduction:
# Django model class RasterModel(models.Model): rast = models.RasterField(srid=4326) # raw sql, single pixel raster with nodata bit set insert into app_rastermodel values(1, REPLACE('01 0000 0100 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 E6100000 0100 0100 6 2 03 03', ' ', '')::raster); # query generating Exception RasterModel.objects.get(pk=1)
Analysis: if we look at the Raster specification, the pixeltype is a byte of which the 4 highest bits are flags and the lowest 4 bits are the real pixeltype, but the Django deserialization code only considers one bit-flag:
# django/contrib/gis/db/backends/postgis/pgraster.py def from_pgraster(data): ... # Subtract nodata byte from band nodata value if it exists has_nodata = pixeltype >= 64 if has_nodata: pixeltype -= 64 ...
The erroneous pixeltype 39 in my example actually had the BANDTYPE_FLAG_ISNODATA
(32) bit set which indicates all rastervalues are nodata.
I have created (my first django) patch and hope somebody can assist me in getting it correct and merged.