'GIS - Can i have multple geo_fields (point, polygon, line) in 1 model and then serialize with DRF?

If I have 1 model with 3 different geo_fields in (point, poly and line), can I serialize all of these with django-rest-framework-gis?

My model:

class Job(BaseModel):
    name = models.CharField(max_length=64)
    desc = models.CharField(max_length=64)

    loc_poly = models.PolygonField(blank=True)
    loc_polyline = models.LineStringField(blank=True)
    loc_point = models.PointField(blank=True)

    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)

Can I serialize by doing something like:

class JobSerializer(GeoFeatureModelSerializer):

    class Meta:
        model = Job
        geo_field = ("loc_point", "loc_polyline", "loc_poly")
        fields = ('__all__',)

Basically can I have geo_field to be multiple geo fields? Or is this only 1?



Solution 1:[1]

No, it is not possible. Consider which of those three fields you want to represent your model if you were to display it on a map.

The geo_field in JobSerializer must represent only one of your geo fields. This is because when it's de-serialized, geo_field will be the representation of what gets displayed on a map.

If you want all three of these features to be displayed simultaneously, I would consider creating intermediary models that link the job to it's feature. You could have something like Job that is just the name/desc and then 3 models (one for each GeoField type) that has the Job as a foreign key.

If you want only one of those fields to display, you could setup the geo_field set to return based on some priority you have set and return the geo features separately like the example below:

class JobSerializer(GeoFeatureModelSerializer):
    loc_poly = serializers.SerializerMethodField()
    loc_polyline = serializers.SerializerMethodField()
    loc_point = serializers.SerializerMethodField()
    display_loc = serializers.SerializerMethodField()

    def get_loc_poly(self, obj):
        json.loads(obj.loc_poly.json)

    def get_loc_polyline(self, obj):
        json.loads(obj.loc_polyline.json)

    def get_loc_point(self, obj):
        json.loads(obj.loc_point.json)

    def get_display_loc(self, obj):
        if obj.loc_poly:
            geom = obj.loc_poly
        elif obj.loc_polyline:
            geom = obj.loc_polyline
        else:
            geom = obj.loc_point
        return json.loads(geom.json)


    class Meta:
        model = Job
        geo_field = 'display_loc'
        fields = ('__all__',)

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