'Django get coordinate values of PointField
I want to get x and y coordinates from the point in the following queryset:
user = User.objects.values('id', 'email', 'username', 'point').first()
These are my models:
from django.db.models import Model
from django.contrib.gis.db.models import PointField
class BasePointModel(Model):
point = PointField(null=True, spatial_index=True, geography=True)
class Meta:
abstract = True
class User(AbstractUser, BasePointModel, HashableModel): # type: ignore
# First Name and Last Name do not cover name patterns
# around the globe.
name = CharField(_("Name of User"), blank=True, max_length=255)
is_online = BooleanField(_("Is online"), default=False)
I am getting the following result:
{'id': 85270,
'email': '[email protected]',
'username': 'username_0',
'point': <Point object at 0x7f8e061cc2b8>}
How can I get an x and y, making a queryset with values?
I want to get something like this:
{'id': 85270,
'email': '[email protected]',
'username': 'username_0',
'point__x': '-4.266398314110177',
'point__y': '-39.39432682357033'}
I make requests that return 50,000 lines from a database, and I notice that performance is getting worse due to data serialization. I want to minimize serialization by returning values.
But the PointField always returns an object, and I still haven't found a way to serialize it in the best way.
Solution 1:[1]
Tough luck :/
You are setting the points as geography and therefore you cannot use a custom GeoFunc in order to apply PostGIS's ST_X and ST_Y in an annotation query because they will only work on geometry fields.
In order to get the [lat, long] values of those points in the values results of the query we can annotate the query with the GeoJSON representation of the points and get those as values. To do that we will use the AsGeoJSON database function:
user = User.objects.annotate(
point_as_json=AsGeoJSON('point')
).values('id', 'email', 'username', 'point_as_json').first()
which will give us the following result:
{
'id': 85270,
'email': '[email protected]',
'username': 'username_0',
'point_as_json': {
'type': 'Point',
'coordinates': [-4.26639831, -39.39432682]
}
}
As a side note, you can consider augmenting Django with django-rest-framework` and use django-rest-framework-gis on top of that which has some very handy tricks on serialization according to GeoJSON standards.
Solution 2:[2]
You could access the __dict__ method of your object and then directly with your geometry:
user = User.objects.values('id', 'email', 'username', 'point').first()
user_dict = user.__dict__
user_dict.update({'point__x':user_dict['point'].x, {'point__y':user_dict['point'].y})
Solution 3:[3]
The best way to get what you need is through a Serializer like the one bellow.
class LayerGeometrySerializer(GeoFeatureModelSerializer):
"""
GeoFeatureModelSerializer is a subclass of rest_framework.ModelSerializer which will output data in a format that is GeoJSON compatible
"""
values = LayerValueMinimalSerializer(source='layervalue_set', many=True)
class Meta:
model = LayerGeometry
geo_field = 'geom'
exclude = ('created', 'modified', )
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | tgrandje |
| Solution 3 | Gonçalo Gomes |
