Passing a model function to geojson serializer in GeoDjango











up vote
1
down vote

favorite












Problem description



Ok, I am trying to add a function defined inside a model (called Highway) to the HttpResponse of the model (Highway) after serializing with geojson serializer without success.



I'm trying to find a solution by going through the source code as no errors are passed and the property does not appear in the HttpResponse. I might however be complicating things and hopefully can get another eyes on this. I'm open to other suggestions, maybe to update the Highway each time a Location is added/modified.



The item appears correctly when passing it to the admin site and all other fields (not shown below) work as intended.



PS. I'm quite new to the whole Django system. Thank you!



Django version: 2.1



Relevant links:




  1. https://docs.djangoproject.com/en/2.1/ref/contrib/gis/serializers/

  2. https://github.com/django/django/blob/master/django/contrib/gis/serializers/geojson.py




Minified code



geom.models.py



class Highway(models.Model):

name = models.CharField(max_length=50, unique=True)
length = models.IntegerField("Length in meters")
mline = models.MultiLineStringField("Geometry", srid=4326)

def cameras_per_km(self):
#THIS IS THE FUNCTION I AM TRYING TO SEND TO GEOJSON SERIALIZER
count = self.location_set.filter(location__icontains="camera").count()
return round(count/(self.length/1000),1)
cameras_per_km.short_description = "Cameras/km"


class Location(models.Model):

location = models.CharField(max_length=30, unique=True)
highway = models.ForeignKey(Highway, null=True, on_delete=models.SET_NULL)
point = models.PointField()


geom.admin.py (when passing the func to list_display the item appears correclty in admin)



class HighwayAdmin(LeafletGeoAdmin):
list_display = ('name', 'cameras_per_km')

admin.site.register(
Highway,
HighwayAdmin,
)


geom.views.py (this doesn't)



def geojson_highway_all(request):

geojsonformat = serialize('geojson',
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km' # <-- I want this to show
)
)

return HttpResponse(geojsonformat)


geom.urls.py



from django.urls import path
from . import views

app_name = 'geom'

urlpatterns = [
path('highways.geojson', views.geojson_highway_all, name='highways.geojson'),
]









share|improve this question
























  • django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
    – Jason
    Nov 17 at 15:26












  • @Jason Thanks for the comment. Might be time to look into the REST framework.
    – Anton vBR
    Nov 17 at 15:47















up vote
1
down vote

favorite












Problem description



Ok, I am trying to add a function defined inside a model (called Highway) to the HttpResponse of the model (Highway) after serializing with geojson serializer without success.



I'm trying to find a solution by going through the source code as no errors are passed and the property does not appear in the HttpResponse. I might however be complicating things and hopefully can get another eyes on this. I'm open to other suggestions, maybe to update the Highway each time a Location is added/modified.



The item appears correctly when passing it to the admin site and all other fields (not shown below) work as intended.



PS. I'm quite new to the whole Django system. Thank you!



Django version: 2.1



Relevant links:




  1. https://docs.djangoproject.com/en/2.1/ref/contrib/gis/serializers/

  2. https://github.com/django/django/blob/master/django/contrib/gis/serializers/geojson.py




Minified code



geom.models.py



class Highway(models.Model):

name = models.CharField(max_length=50, unique=True)
length = models.IntegerField("Length in meters")
mline = models.MultiLineStringField("Geometry", srid=4326)

def cameras_per_km(self):
#THIS IS THE FUNCTION I AM TRYING TO SEND TO GEOJSON SERIALIZER
count = self.location_set.filter(location__icontains="camera").count()
return round(count/(self.length/1000),1)
cameras_per_km.short_description = "Cameras/km"


class Location(models.Model):

location = models.CharField(max_length=30, unique=True)
highway = models.ForeignKey(Highway, null=True, on_delete=models.SET_NULL)
point = models.PointField()


geom.admin.py (when passing the func to list_display the item appears correclty in admin)



class HighwayAdmin(LeafletGeoAdmin):
list_display = ('name', 'cameras_per_km')

admin.site.register(
Highway,
HighwayAdmin,
)


geom.views.py (this doesn't)



def geojson_highway_all(request):

geojsonformat = serialize('geojson',
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km' # <-- I want this to show
)
)

return HttpResponse(geojsonformat)


geom.urls.py



from django.urls import path
from . import views

app_name = 'geom'

urlpatterns = [
path('highways.geojson', views.geojson_highway_all, name='highways.geojson'),
]









share|improve this question
























  • django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
    – Jason
    Nov 17 at 15:26












  • @Jason Thanks for the comment. Might be time to look into the REST framework.
    – Anton vBR
    Nov 17 at 15:47













up vote
1
down vote

favorite









up vote
1
down vote

favorite











Problem description



Ok, I am trying to add a function defined inside a model (called Highway) to the HttpResponse of the model (Highway) after serializing with geojson serializer without success.



I'm trying to find a solution by going through the source code as no errors are passed and the property does not appear in the HttpResponse. I might however be complicating things and hopefully can get another eyes on this. I'm open to other suggestions, maybe to update the Highway each time a Location is added/modified.



The item appears correctly when passing it to the admin site and all other fields (not shown below) work as intended.



PS. I'm quite new to the whole Django system. Thank you!



Django version: 2.1



Relevant links:




  1. https://docs.djangoproject.com/en/2.1/ref/contrib/gis/serializers/

  2. https://github.com/django/django/blob/master/django/contrib/gis/serializers/geojson.py




Minified code



geom.models.py



class Highway(models.Model):

name = models.CharField(max_length=50, unique=True)
length = models.IntegerField("Length in meters")
mline = models.MultiLineStringField("Geometry", srid=4326)

def cameras_per_km(self):
#THIS IS THE FUNCTION I AM TRYING TO SEND TO GEOJSON SERIALIZER
count = self.location_set.filter(location__icontains="camera").count()
return round(count/(self.length/1000),1)
cameras_per_km.short_description = "Cameras/km"


class Location(models.Model):

location = models.CharField(max_length=30, unique=True)
highway = models.ForeignKey(Highway, null=True, on_delete=models.SET_NULL)
point = models.PointField()


geom.admin.py (when passing the func to list_display the item appears correclty in admin)



class HighwayAdmin(LeafletGeoAdmin):
list_display = ('name', 'cameras_per_km')

admin.site.register(
Highway,
HighwayAdmin,
)


geom.views.py (this doesn't)



def geojson_highway_all(request):

geojsonformat = serialize('geojson',
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km' # <-- I want this to show
)
)

return HttpResponse(geojsonformat)


geom.urls.py



from django.urls import path
from . import views

app_name = 'geom'

urlpatterns = [
path('highways.geojson', views.geojson_highway_all, name='highways.geojson'),
]









share|improve this question















Problem description



Ok, I am trying to add a function defined inside a model (called Highway) to the HttpResponse of the model (Highway) after serializing with geojson serializer without success.



I'm trying to find a solution by going through the source code as no errors are passed and the property does not appear in the HttpResponse. I might however be complicating things and hopefully can get another eyes on this. I'm open to other suggestions, maybe to update the Highway each time a Location is added/modified.



The item appears correctly when passing it to the admin site and all other fields (not shown below) work as intended.



PS. I'm quite new to the whole Django system. Thank you!



Django version: 2.1



Relevant links:




  1. https://docs.djangoproject.com/en/2.1/ref/contrib/gis/serializers/

  2. https://github.com/django/django/blob/master/django/contrib/gis/serializers/geojson.py




Minified code



geom.models.py



class Highway(models.Model):

name = models.CharField(max_length=50, unique=True)
length = models.IntegerField("Length in meters")
mline = models.MultiLineStringField("Geometry", srid=4326)

def cameras_per_km(self):
#THIS IS THE FUNCTION I AM TRYING TO SEND TO GEOJSON SERIALIZER
count = self.location_set.filter(location__icontains="camera").count()
return round(count/(self.length/1000),1)
cameras_per_km.short_description = "Cameras/km"


class Location(models.Model):

location = models.CharField(max_length=30, unique=True)
highway = models.ForeignKey(Highway, null=True, on_delete=models.SET_NULL)
point = models.PointField()


geom.admin.py (when passing the func to list_display the item appears correclty in admin)



class HighwayAdmin(LeafletGeoAdmin):
list_display = ('name', 'cameras_per_km')

admin.site.register(
Highway,
HighwayAdmin,
)


geom.views.py (this doesn't)



def geojson_highway_all(request):

geojsonformat = serialize('geojson',
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km' # <-- I want this to show
)
)

return HttpResponse(geojsonformat)


geom.urls.py



from django.urls import path
from . import views

app_name = 'geom'

urlpatterns = [
path('highways.geojson', views.geojson_highway_all, name='highways.geojson'),
]






python django geojson django-serializer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 at 15:18

























asked Nov 17 at 14:33









Anton vBR

11.2k2922




11.2k2922












  • django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
    – Jason
    Nov 17 at 15:26












  • @Jason Thanks for the comment. Might be time to look into the REST framework.
    – Anton vBR
    Nov 17 at 15:47


















  • django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
    – Jason
    Nov 17 at 15:26












  • @Jason Thanks for the comment. Might be time to look into the REST framework.
    – Anton vBR
    Nov 17 at 15:47
















django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
– Jason
Nov 17 at 15:26






django's default serializers really aren't suitable for anything beyond dumping or loading fixture data. this is one of the pain points for which django rest framework was created. For more info on why you should use DRF, check out reddit.com/r/django/comments/3h9oj8/… for a breakdown on this and similar points. Also, if you're spitting out json data and making a restful api, I would look at integrating DRF or tastypie into your project because it will make working in the backend much easier
– Jason
Nov 17 at 15:26














@Jason Thanks for the comment. Might be time to look into the REST framework.
– Anton vBR
Nov 17 at 15:47




@Jason Thanks for the comment. Might be time to look into the REST framework.
– Anton vBR
Nov 17 at 15:47












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










Update: I (Anton vBR) have now rewritten this answer completely but think @ruddra deserves some credit. I am however open for alternative solutions. Hopefullly this answer can helps someone out in the future.





Create a new Serializer based on geojson serializer



geom.views.py



from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

def end_object(self, obj):
for field in self.selected_fields:
if field == self.geometry_field or field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj, field)()
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)

geojsonformat = CustomSerializer().serialize(
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km'
)





share|improve this answer























  • add @property decorator on cameras_per_km and check again :)
    – ruddra
    Nov 17 at 16:01










  • Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
    – ruddra
    Nov 17 at 16:11












  • Please see my update section
    – ruddra
    Nov 17 at 16:43










  • Sure, looks more elegant than mine.
    – ruddra
    Nov 17 at 18:39






  • 1




    Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
    – Anton vBR
    Nov 17 at 21:21













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53352196%2fpassing-a-model-function-to-geojson-serializer-in-geodjango%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Update: I (Anton vBR) have now rewritten this answer completely but think @ruddra deserves some credit. I am however open for alternative solutions. Hopefullly this answer can helps someone out in the future.





Create a new Serializer based on geojson serializer



geom.views.py



from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

def end_object(self, obj):
for field in self.selected_fields:
if field == self.geometry_field or field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj, field)()
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)

geojsonformat = CustomSerializer().serialize(
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km'
)





share|improve this answer























  • add @property decorator on cameras_per_km and check again :)
    – ruddra
    Nov 17 at 16:01










  • Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
    – ruddra
    Nov 17 at 16:11












  • Please see my update section
    – ruddra
    Nov 17 at 16:43










  • Sure, looks more elegant than mine.
    – ruddra
    Nov 17 at 18:39






  • 1




    Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
    – Anton vBR
    Nov 17 at 21:21

















up vote
1
down vote



accepted










Update: I (Anton vBR) have now rewritten this answer completely but think @ruddra deserves some credit. I am however open for alternative solutions. Hopefullly this answer can helps someone out in the future.





Create a new Serializer based on geojson serializer



geom.views.py



from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

def end_object(self, obj):
for field in self.selected_fields:
if field == self.geometry_field or field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj, field)()
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)

geojsonformat = CustomSerializer().serialize(
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km'
)





share|improve this answer























  • add @property decorator on cameras_per_km and check again :)
    – ruddra
    Nov 17 at 16:01










  • Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
    – ruddra
    Nov 17 at 16:11












  • Please see my update section
    – ruddra
    Nov 17 at 16:43










  • Sure, looks more elegant than mine.
    – ruddra
    Nov 17 at 18:39






  • 1




    Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
    – Anton vBR
    Nov 17 at 21:21















up vote
1
down vote



accepted







up vote
1
down vote



accepted






Update: I (Anton vBR) have now rewritten this answer completely but think @ruddra deserves some credit. I am however open for alternative solutions. Hopefullly this answer can helps someone out in the future.





Create a new Serializer based on geojson serializer



geom.views.py



from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

def end_object(self, obj):
for field in self.selected_fields:
if field == self.geometry_field or field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj, field)()
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)

geojsonformat = CustomSerializer().serialize(
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km'
)





share|improve this answer














Update: I (Anton vBR) have now rewritten this answer completely but think @ruddra deserves some credit. I am however open for alternative solutions. Hopefullly this answer can helps someone out in the future.





Create a new Serializer based on geojson serializer



geom.views.py



from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

def end_object(self, obj):
for field in self.selected_fields:
if field == self.geometry_field or field == 'pk':
continue
elif field in self._current.keys():
continue
else:
try:
self._current[field] = getattr(obj, field)()
except AttributeError:
pass
super(CustomSerializer, self).end_object(obj)

geojsonformat = CustomSerializer().serialize(
Highway.objects.all(),
geometry_field='mline',
fields = (
'pk',
'cameras_per_km'
)






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 17 at 21:06









Anton vBR

11.2k2922




11.2k2922










answered Nov 17 at 15:28









ruddra

7,97332546




7,97332546












  • add @property decorator on cameras_per_km and check again :)
    – ruddra
    Nov 17 at 16:01










  • Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
    – ruddra
    Nov 17 at 16:11












  • Please see my update section
    – ruddra
    Nov 17 at 16:43










  • Sure, looks more elegant than mine.
    – ruddra
    Nov 17 at 18:39






  • 1




    Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
    – Anton vBR
    Nov 17 at 21:21




















  • add @property decorator on cameras_per_km and check again :)
    – ruddra
    Nov 17 at 16:01










  • Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
    – ruddra
    Nov 17 at 16:11












  • Please see my update section
    – ruddra
    Nov 17 at 16:43










  • Sure, looks more elegant than mine.
    – ruddra
    Nov 17 at 18:39






  • 1




    Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
    – Anton vBR
    Nov 17 at 21:21


















add @property decorator on cameras_per_km and check again :)
– ruddra
Nov 17 at 16:01




add @property decorator on cameras_per_km and check again :)
– ruddra
Nov 17 at 16:01












Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
– ruddra
Nov 17 at 16:11






Maybe this will help: stackoverflow.com/a/39190681/2696165 or add readonly_fields = ('cameras_per_km',) in HighwayAdmin
– ruddra
Nov 17 at 16:11














Please see my update section
– ruddra
Nov 17 at 16:43




Please see my update section
– ruddra
Nov 17 at 16:43












Sure, looks more elegant than mine.
– ruddra
Nov 17 at 18:39




Sure, looks more elegant than mine.
– ruddra
Nov 17 at 18:39




1




1




Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
– Anton vBR
Nov 17 at 21:21






Ok I think I am done. By adding () to getattr we can call the model functions right away. This is now only done if selected_fields have not been used. This also helps us to get around @property.
– Anton vBR
Nov 17 at 21:21




















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53352196%2fpassing-a-model-function-to-geojson-serializer-in-geodjango%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin