Skip to content
Advertisement

Saving centroid of a (multi)polygon as point geometry in a model

I have two tables, one with multipolygon geometries, the other with a column for point geometries. I want the centroid of the selected polygon to be saved as the point geometry for the other table.

class matview_all_administrative_units(models.Model):
    lau_id = models.IntegerField(primary_key=True)
    ortsgemeinde = models.CharField(max_length=150)
    verwaltungsgemeinde = models.CharField(max_length=150)
    landkreis_bezirk = models.CharField(max_length=150)
    bundesland_kanton = models.CharField(max_length=150)
    staat = models.CharField(max_length=150)
    geom = models.MultiPolygonField(srid=4326)

    class Meta:
        managed = False
        db_table = 'administrative_hierarchy_full_geom'

class site(models.Model):
    sid = models.AutoField(primary_key=True)
    site_name = models.CharField(max_length=250)
    site_notes = models.CharField(max_length=2500, blank=True, null=True)
    municipality = models.ForeignKey('local_administrative_unit', on_delete=models.PROTECT)
    geom = models.PointField(srid=4326)

    def __str__(self):
        return '{}, {} ({})'.format(self.sid, self.site_name, self.municipality)

To add a new site, an existing administrative unit must be associated with it and the center of it’s polygon should be used as the location/geometry of the site. For now I made this:

class NewSiteView(CreateView):

    model = models.site
    form_class = forms.NewSiteForm
    template_name = 'datamanager/newsite.html'
    success_url = '/sites/'

calling this form:

from django.forms import ModelForm, HiddenInput
from django.contrib.gis.db.models.functions import Centroid
from . import models

class NewSiteForm(ModelForm):

    class Meta:
        model = models.site
        fields = ['site_name', 'site_notes', 'municipality','geom']
    

    widgets = {
        'geom': HiddenInput(),
    }
    def clean(self):
        super().clean()
        self.cleaned_data['geom'] = Centroid(models.matview_all_administrative_units.objects.values('geom').filter(lau_id=self.cleaned_data['municipality'].lau_id))

however, this leads to this error:

enter image description here

So I am basically not calculating a point but a ‘centroid object’ – so far so good, the django documentation tells us that. Now I am stuck trying to get something out of this centroid thingy that I can shove into that geometry column. As far as I understand I take the right data and handle it over to the right function (otherwise the error should appear earlier in this code i think?), but the result is not useful for inserting it into a geometry column. So how do i get my point? (lol)

Advertisement

Answer

finally I found a solution. Added this to the CreateView:

def form_valid(self, form):

pol = models.local_administrative_unit.objects.values('geom').filter(lau_id=form.cleaned_data['municipality'].lau_id)[0]['geom']
cent_point = pol.centroid
form.instance.geom = cent_point.wkt
form.save()

return super().form_valid(form)

I takes the geometry from the polygon, calculates the centroid of it and inserts it’s geometry as well-known text into the form, then saves the form.

Advertisement