1

I have two models and need to serialize Article as Geojson by setting the geo_field attribute as point from the Location model. After following the solution given here I get the error:

Got AttributeError when attempting to get a value for field `point` on serializer `ArticleSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Article` instance.
Original exception text was: 'ManyRelatedManager' object has no attribute 'point'.

Here are my models:

class Location(models.Model):
    city = models.CharField(max_length=200)
    point = models.PointField(srid=4326)
    objects = models.GeoManager()

class Article(models.Model):
    locations = models.ManyToManyField(Location)
    article_title = models.CharField(max_length=200)

    @property
    def point(self):
    return self.locations.point

And my serializer:

class ArticleSerializer(GeoFeatureModelSerializer):
point = GeometryField()

class Meta:
    model = Article
    geo_field = "point"
    id_field = False
    fields = ('pub_date', 'point',)

Any help appreciated. I've been trying to find a solution to this for ages with little success!

UPDATE!

Ok, getting somewhere with this. I created a LocationSerializer and reference this in ArticleSerializer. These now look something like this:

class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        geo_field = "point"
        id_field = False
        fields = ('point',)

class ArticleSerializer(GeoFeatureModelSerializer):
    locations = LocationSerializer(many=True)       
    class Meta:
        model = Article
        geo_field = "locations"
        id_field = False
        fields = ('pub_date', 'locations',)

The output is closer to what I want...but still a bit obscure in construct:

{  
    "type":"FeatureCollection",
    "features":[  
        {  
            "type":"Feature",
            "geometry":[  
                {  
                    "point":{  
                        "type":"Point",
                        "coordinates":[  
                            -2.200337956118645,
                            53.48316423741371
                        ]
                    }
                },
                {  
                    "point":{  
                        "type":"Point",
                        "coordinates":[  
                            0.041198730463564,
                            51.51002453017606
                        ]
                    }
                }
            ],
            "properties":{  
                "pub_date":"2015-04-06T20:38:59Z"
            }
        }
    ]
}

UPDATE!

The format I require is:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "time": "2013-01-22 08:42:26+01"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    7.582512743,
                    51.933292258,
                    1
                ]
            }
        },
sammy88888888
  • 458
  • 1
  • 5
  • 18

2 Answers2

0

The issue is that your point property on the Article model is referring to self.locations which is a ManyToManyField. You are calling self.locations.point as though self.locations is a ForeignKey which is why you are getting your error.

'ManyRelatedManager' object has no attribute 'point'.

Means that self.locations is returning a ManyRelatedManager, which makes sense for a ManyToManyField. Since you are only expecting a single object, that means you need to make one of two changes

  1. You really were looking to have locations be a ForeignKey, which would mean your point property is correct.
  2. You are actually expecting multiple locations for an Article, and your point property should actually be returning a list of points.

    return [location.point for location in self.locations]
    

If you are actually looking for multiple locations, you are also going to want to set many=True on your GeometryField on your serializer.

Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
  • Yeah I am expecting either one or more `locations` for each `Article`. I've tried making the changes but `GeometryField` doesn't like to be set to `many`, I am getting the error: `__init__() got an unexpected keyword argument 'many'`. Without setting this I get the error: `'ManyRelatedManager' object is not iterable`. – sammy88888888 May 06 '15 at 02:28
  • Ok, I think I'm a bit closer. I added `.all()` to the `self.locations` and am now getting `Improper geometry input type: ` error. Any thoughts? – sammy88888888 May 06 '15 at 16:06
  • It sounds like the `GeometryField` is only designed to work with a single point, you might have some luck wrapping it in a `ListField`. – Kevin Brown-Silva May 06 '15 at 16:07
  • Updated my question above. Don't know if this spurs any thoughts? – sammy88888888 May 06 '15 at 17:46
  • @sammy88888888 Is the output what you are expecting or are you looking for something different? – Kevin Brown-Silva May 06 '15 at 19:32
  • I'm looking for something different, I've udated above to show the required format. The idea is to serialize as geojson and pass to [LeafletSlider](https://github.com/dwilhelm89/LeafletSlider). – sammy88888888 May 06 '15 at 19:42
0

Ok, the solution seems to be...don't do it the way I was attempting. I've got round the bulk of the problem by using vectorformats.DjangoWStyle (just search google) to deal with searializing geojson from two models. Also, attempting a reverse relationship to achives this will lead to a world of misery. Instead I added the ManyToManyField on Location model, referencing the Article model.

sammy88888888
  • 458
  • 1
  • 5
  • 18