Search code examples
mysqldjangopython-3.xgeojson

Python bytes to geojson Point


I have a MySQL database where I have Point type location data and a Django (Django Rest Framework) backend where I am trying to retrieve that data. If I try to get that location data from phpMyAdmin the returned location is something like this POINT(23.89826 90.267535). In my Django backend however, I get a bytes as the returned location. The returned value is something like this b'\x00\x00\x00\x00\x01\x01\x00\x00\x00\x12N\x0b^\xf4\xe57@C\xe2\x1eK\x1f\x91V@'

The database uses utf8mb4_unicode_ci collation.

If I try to convert the returned bytes to a string with .decode('utf-8') I get UnicodeDecodeError

>>> s = b'\x00\x00\x00\x00\x01\x01\x00\x00\x00\x12N\x0b^\xf4\xe57@C\xe2\x1eK\x1f\x91V@'
>>> s.decode('utf-8')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf4 in position 13: invalid continuation byte

I get the same bytes array even if I perform a raw query from Django with the MySQL function St_AsGeoJson(location).

I then tried geojson. When I feed that bytes to geojson.Point() I get a geojson back but instead of 2 floats the coordinates array consists 25 integer values.

>>> s = b'\x00\x00\x00\x00\x01\x01\x00\x00\x00\x12N\x0b^\xf4\xe57@C\xe2\x1eK\x1f\x91V@'
>>> geojson.Point(s)
{"coordinates": [0, 0, 0, 0, 1, 1, 0, 0, 0, 18, 78, 11, 94, 244, 229, 55, 64, 67, 226, 30, 75, 31, 145, 86, 64], "type": "Point"}

How can I retrieve the Point data from the bytes or this geojson?


Solution

  • I had this problem because I was using plain Django and Django models doesn't have a field type that deals with Geo data. I was using a CharField with a max_length=255 and then tried to parse whatever that CharField retrieved from the database. I have solved the problem by using GeoDjango and Django REST Framework GIS. Django REST Framework GIS is not necessary. I used it because I am using Django REST Framework and it outputs the Geo data in a nice format.

    Steps were to

    1. Install GDAL(Geospatial Data Abstraction Library)

      sudo apt-get install gdal-bin sudo apt-get install python3-gdal

    2. Add django.contrib.gis and rest_framework_gis to settings.INSTALLED_APPS

    3. Set GDAL_LIBRARY_PATH in settings, in my case it's GDAL_LIBRARY_PATH = os.getenv('GDAL_LIBRARY_PATH')
    4. Update model import from from django.db import models to from django.contrib.gis.db import models
    5. Update the model to use a Geo field. More: https://docs.djangoproject.com/en/2.1/ref/contrib/gis/model-api/

    Links