Search code examples
djangoadminpointgeodjango

Geodjango admin, display pointfield not as map


This may be a stupid question but I can't find any clear answers.

How do I change the display in the Django Admin so the Pointfield does not show up like a OpenLayer Map but as a regular input field. I need to see the long, lat for debugging..

Do i have to change the field type? Widgets?

Thanks!


Solution

  • Update

    This is how I managed -at last- to keep separate fields for lattitude and longitude without having to save them in the database since the values are already saved in the PointField.

    The idea is :

    • If we are inserting a new entry, the latitude and longitude fields will be used to set the PointField
    • If we open an existing PointField entry, it will be used to provide the latitude and longitude values in the relevant FormFields.

    models.py

    from django.contrib.gis.db import models as geomodels
    
    
    class Entry(geomodels.Model):
        point = geomodels.PointField(
            srid=4326,
            blank=True,
            )
    

    admin.py

    from myapp.forms import EntryForm
    from django.contrib import admin
    
    
    class EntryAdmin(admin.ModelAdmin):
        form = EntryForm
    
    
    admin.site.register(Entry, EntryAdmin)
    

    forms.py

    from django import forms
    from myapp.models import Entry
    from django.contrib.gis.geos import Point
    
    
    class MarketEntryForm(forms.ModelForm):
    
        latitude = forms.FloatField(
            min_value=-90,
            max_value=90,
            required=True,
        )
        longitude = forms.FloatField(
            min_value=-180,
            max_value=180,
            required=True,
        )
    
        class Meta(object):
            model = MarketEntry
            exclude = []
            widgets = {'point': forms.HiddenInput()}
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            coordinates = self.initial.get('point', None)
            if isinstance(coordinates, Point):
                self.initial['longitude'], self.initial['latitude'] = coordinates.tuple
    
        def clean(self):
            data = super().clean()
            latitude = data.get('latitude')
            longitude = data.get('longitude')
            point = data.get('point')
            if latitude and longitude and not point:
                data['point'] = Point(longitude, latitude)
            return data
    

    From the source code of PointField we see that its form class uses the OpenLayersWidget which inherits from the BaseGeometryWidget.

    The conclusion is that in this class, the variable display_raw is by default set to False.

    If you set it to True in yourapp/admin.py, you will get a textbox with lat and long and other data, useful for debugging purposes:

    from django.contrib.gis import admin
    from yourapp.models import YourClass
    from django.contrib.gis import forms
    from django.contrib.gis.db import models    
    
    
    class YourClassAdminForm(forms.ModelForm):
        your_attribute = forms.PointField(widget=forms.OSMWidget(attrs={
                'display_raw': True}))
    
    class YourClassAdmin(admin.GeoModelAdmin):
        form = YourClassAdminForm
    
    
    admin.site.register(YourClass, YourClassAdmin)
    

    There is also a way to have both a map and manual insertion of longitude / latitude permanently (not only for debugging).

    The idea is to use FloatFields to insert the Longitude/Latitude and update the PointField with the inserted data.