GeoDjango newbie here. In short, I have:
- project set up with GeoDjango using PostgreSQL/PostGIS
- user can input address which is geocoded with Nominatum
- uses OSMnx/Geopandas/Shapely for getting Open Street Map boundaries
- note: I’m not necessarily beholden to using any of the above (except PostgreSQL) but just these are what I have implemented right now
What I want: find and save relevant Location objects based on a geocoded address being within their geometries. I’m going in circles for how to do this without the request taking ~10+ minutes or timing out.
This nyc-boundaries example shows what I mean (how one address is related to different boundaries and those boundaries overlap in different geometries). Not GeoDjango, but nyc-boundary example code here. Unlike that project (provided more for communicating what I mean for searching), my project would not have a display of the map and would save the relations via UserLocation.
Questions
- Do you know of any public example code for GeoDjango projects that do something like the above?
- note: I already went through the GeoDjango tutorial/the GeoDjango docs/GeoDjango DjangoCon videos already which is how I’ve gotten as far as I have (#grateful)
- Is using the geocoded address to find the relevant geometries a recommended approach for this? / Are there other approaches you’d take instead?
- In one of my attempts to simplify, I tried skirting my struggles with the geometry which is how I ended up with the
OCDDivisionmodel (more about OCD Divisions here). The short version of this is that I struggled to establish a reliable way to 1) link an address to an OCD-ID (did find this so going to explore that) and 2) link an OCD-ID to a geometry. The (seemingly) best linking I found only addressed >1% of the ~965K OCD-IDs in the United States. So now I’m back to seeing if there’s a way to make the geometries approach work. - Related to the above, I’m also investigating some paid options (geocodio, BallotReady, etc.) which I’m open to exploring more. If anyone has direct experience with services that do this (even if it’s paid and even if it’s for places outside of the United States), I’d be curious know if you would/wouldn’t recommend the service you use.
- I also considered having the user search for their own relevant locations and then saving them manually, but then the purpose of discovering
Locations relevant to a user is lost (which is important in this case, sort of similar in some ways to the purpose behind nyc-boundaries)
- In one of my attempts to simplify, I tried skirting my struggles with the geometry which is how I ended up with the
PS: I have a lot more context on what I’ve tried/researched (so many things…
), but tried to keep this post short because I first attempted writing all the context and it was becoming quite the book which I thought was becoming more confusing than helpful
model excerpts:
class Location(models.Model):
TYPE_CHOICES = [
("division", "OCD Division"),
("address", "Address"),
]
name = models.CharField(max_length=255)
type = models.CharField(
max_length=50,
choices=TYPE_CHOICES,
null=True,
blank=True,
help_text="Type of the location, e.g., OCD division or address",
)
parents = models.ManyToManyField(
"self",
symmetrical=False,
related_name="children",
help_text="Parent/s for a Location, "
"e.g. as defined by the OCD-id division hierarchy, etc.",
)
geometry = models.GeometryField(null=True, blank=True)
osm_id = models.BigIntegerField(
unique=True, null=True, blank=True
)
osm_admin_level = models.IntegerField(null=True, blank=True)
ocd_division = models.OneToOneField(
"OCDDivision", null=True, blank=True, on_delete=models.PROTECT
)
# through model
class UserLocation(models.Model):
user_profile = models.ForeignKey("persons.UserProfile", on_delete=models.CASCADE)
location = models.ForeignKey(Location, on_delete=models.CASCADE)
class Meta:
unique_together = ("user_profile", "location")
class OCDDivision(models.Model):
ocd_id = models.CharField(
max_length=255,
primary_key=True,
help_text="OCD division ID (e.g. ocd-division/country:us/state:ny/county:albany)",
)
name = models.CharField(max_length=255)
type = models.CharField(
max_length=50,
blank=True,
null=True,
help_text="Type of division (state, county, place, cd, sldl, etc)",
)
type_id = models.CharField(
max_length=100,
blank=True,
null=True,
help_text="Identifier for the type (e.g. 'ny' for state:ny)",
)