I recently received this requirement and got a little carried away, but I thought I would share it. (Django 2.0.)
I created a 30-character CharField to contain the coordinates entered, for example. N 35ΒΊ 44.265 W 41ΒΊ 085.155 (I have no idea where it is, by the way ...) and arranged for the Model to save the field values.
import re from django.core.exceptions import ValidationError COORDINATES_REGEX = r'(?:[NS])\s*([0-9]{2})[\ΒΊ\Β°]?\s+([0-9]{1,3}\.[0-9]{3})\s*(?:[EW])\s*([0-9]{2,3})[\ΒΊ\Β°]?\s+([0-9]{2,3}\.[0-9]{3})' def decode_coords_string(str): """ Given a string, converts it to a decimal (lat, lng, 'OK', matched_string) tuple. If invalid, returns "(None, None, <some reason>, None)." Test for errors by checking that the coordinate is not 'None.' 'matched_string' returns the actual extent of the matched string regardless of where in the input-string it was, for sanitizing the input when storing it in the database. (If the input string contains only blanks, we should store an empty-string.) The model will replace the field-value with this matched-string. """
CharField input indicates validators=[validate_coords] Note that degrees can be specified in several ways or omitted altogether.
And the model includes the following short method:
def save(self, *args, **kwargs): """ Calculate and automatically populate the numeric lat/long figures. This routine assumes that the string is either empty or that it has been validated. An empty string β or, for that matter, an invalid one β will be (None, None). """ ( lat, lng, reason, cleaned) = decode_coords_string(self.coordinate_str) self.coordinate_str = cleaned self.latitude = lat self.longitude = lng super().save(*args, **kwargs)
In admin.py I exclude the latitude and longitude fields (both of which are Float fields) from the view to avoid confusion with the user. Numeric fields are automatically calculated but not displayed.