Geodjango admin, display pointfield not as map
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.DecimalField(
min_value=-90,
max_value=90,
required=True,
)
longitude = forms.DecimalField(
min_value=-180,
max_value=180,
required=True,
)
class Meta(object):
model = MarketEntry
exclude = []
widgets = {'point': forms.HiddenInput()}
def clean(self):
super().clean()
if any(x for x in ['latitude', 'longitude'] if x in self.changed_data):
latitude = float(self.cleaned_data['latitude'])
longitude = float(self.cleaned_data['longitude'])
self.cleaned_data['point'] = Point(longitude, latitude)
def __init__(self, *args, **kwargs):
try:
coordinates = kwargs['instance'].point.tuple #If PointField exists
initial = kwargs.get('initial', {})
initial['longitude'] = coordinates[0] #Set longitude from coordinates
initial['latitude'] = coordinates[1] #Set Latitude from coordinates
kwargs['initial'] = initial
except (KeyError, AttributeError):
pass
super().__init__(*args, **kwargs)
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.
You can override a widget with another in Django admin. From the documentation -
from django.db import models
from django.contrib import admin
# Import our custom widget and our model from where they're defined
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': RichTextEditorWidget},
}
This overrides TextField
with RichTextEditorWidget
. Just find the field type for point field and override it with TextField.