Geographical database for internal projects.
Project description
WebCase Geographical database
Installation
pip install wc-django-geo-db
In settings.py
:
INSTALLED_APPS += [
'pxd_lingua',
'pxd_postgres',
'pxd_postgres.ltree',
'wcd_geo_db',
'wcd_geo_db.contrib.admin',
'wcd_geo_db_sources',
]
WCD_GEO_DBSOURCES = {
'SOURCE_IMPORT_RUNNERS': (
'wcd_geo_db_sources.sources.katottg.process.KATOTTGImportRunner',
'wcd_geo_db_sources.sources.katottg_to_koatuu.process.KATOTTG_TO_KOATUUImportRunner',
)
}
Usage
from wcd_geo_db.client import GeoClient
from wcd_geo_db.conf import Settings
from wcd_geo_db.modules.code_seeker import registry
from wcd_geo_db_sources.sources.koatuu import KOATUU_SEEKER
from wcd_geo_db_sources.sources.katottg import KATOTTG_SEEKER
from wcd_geo_db_sources.sources.novaposhta import NOVAPOSHTA_SEEKER
client = GeoClient(settings=Settings(), code_seeker_registry=registry)
registry.register(KOATUU_SEEKER)
registry.register(KATOTTG_SEEKER)
registry.register(NOVAPOSHTA_SEEKER)
client.bank.divisions.get(ids=(1,))
found = client.bank.divisions.find(levels=(DivisionLevel.ADMINISTRATIVE_LEVEL_1,))
descendants = client.bank.divisions.find_descendants(ids=found)
# Since [0.1.15].
# Divisions can be search by `label` field now.
# Label is a sluggified version of `name` field. Unique, but there is no
# constraint on that.
client.bank.divisions.find(labels=('odesa',))
Different DTOs to resolve
Since [0.1.15
].
You may now choose in what variation you can retrieve your data.
There is only 2 options right now:
- as
DivisionDTO
- It's simple, but provide all the data you need for regular use. Used by default. - as
ExtendedDivisionDTO
- Provides additional geography info(location, polygon) and prefix name definition.
from wcd_geo_db.modules.bank.dtos import DivisionDTO, ExtendedDivisionDTO
# ...
# Will result in List[DivisionDTO].
client.bank.divisions.get(ids=(1,))
# Same as before: List[DivisionDTO].
client.bank.divisions.get(ids=(1,), as_dto=DivisionDTO)
# Here result changes: List[ExtendedDivisionDTO].
client.bank.divisions.get(ids=(1,), as_dto=ExtendedDivisionDTO)
TODO: Make DTO resolvers extend API to be public.
Address formatter
address = client.addresses.formatter.format_addresses(
(
# Sequence of address definitions.
{
# There could be either identifiers or DivisionDTOs in a list.
'divisions_path': [1, 2],
# Or you can pass a division identifer or DivisionDTO as single.
'division': 2,
# If both `divisions_path` and `division` will be passed - `divisions_path`
# field will be used to get address information.
},
),
# Main language to use for formatting.
'en',
# Languages to use if there's no default one
fallback_languages=('es', 'jp')
)
print(address.formatted_address)
# > 'Administrative division level 1, Country name'
Since [0.1.15
]. Added translatable division name prefixes, that now can will be used in address formatting.
Searching
search = client.bank.divisions.find(search_query={
'query': 'Santa Monica',
'language': 'en',
})
print(search)
# Search results will be ordered by relevance rank.
# > [438, 335. 425]
Since [0.1.12
]. Added use_simple_search
parameter to divisions search. It forces search mechanics to use simple __icontains
instead of trigram similarity. Query will run faster but response wouldn't be ordered by search matching relevance:
search = client.bank.divisions.find(search_query={
'query': 'Santa Monica',
'use_simple_search': True,
'language': 'en',
})
Contrib
DAL
Since [0.1.12
].
To use django autocomplete light you need to install library with [dal]
extras.
Like so:
pip install wc-django-geo-db[dal]
Urls
Default autocomplete urls could be made as:
# Importing url factory.
from wcd_geo_db.contrib.dal.urls import make_urlpatterns
# Importing defined GeoClient instance somewhere from your project:
from your_project.geo_client import client
urlpatterns = [
# And including newly made urlpatterns into yours.
path('', include(make_urlpatterns(client))),
]
Namespace for all autocomplete url is 'wcd-geo-db:dal:admin:autocomplete'
.
So for example divisions autocomplete url looks like: 'wcd-geo-db:dal:admin:autocomplete:divisions'
.
There are custom url makers also available:
from django.urls import path, include
from wcd_geo_db.const import DivisionLevel
from wcd_geo_db.contrib.dal.urls import make_urlpatterns, make_divisions_path, autocomplete_namespace
from wcd_geo_db.contrib.dal.views import DivisionDalViewAdmin
from your_project.geo_client import client
urlpatterns = [
# URLs may be extended, all of them are going to be under the same
# autocomplete namespace.
path('', include(make_urlpatterns(
client,
# For example you want to add url that displays only localities,
# not all divisions.
# It may be just a custom path, but we already have a generator, so use it:
make_divisions_path(
# Name for url.
'localities',
# Client also must be provided.
client,
# This is just kwargs for divisions.find() method.
find_parameters={'levels': [DivisionLevel.LOCALITY]},
# cls attribute may be omitted, but by default it's a view with no
# access restriction. But since this is admin view we must use an
# appropriated.
# This could be any custom view, of course.
cls=DivisionDalViewAdmin
)
))),
]
After this you can use your new autocompletetion urls anywhere. For example above url name will be: 'wcd-geo-db:dal:admin:autocomplete:localities'
.
Admin integration
To use autocomplete urls in admin you may do something like this:
your_application/admin.py
from dal_select2.widgets import ModelSelect2Multiple
from wcd_geo_db.contrib.dal.djhacker import formfield
from wcd_geo_db.contrib.dal.forms import PreparableModelMultipleChoiceField
from wcd_geo_db.contrib.dal.preparators import DivisionsPreparator
from your_project.geo_client import client
from .models import YourCustomModel
# With help of `djhacker` you wouldn't need to manually override formfields
# without creating custom forms for that:
formfield(
# URL name to autocomplete divisions:
'wcd-geo-db:dal:admin:autocomplete:divisions',
# Your model field to patch:
YourCustomModel.division_singular_field,
# Special data resolver for divisions data that formats divisions
# as addresses.
preparator=DivisionsPreparator(
client=client.bank.divisions,
formatter_client=client.addresses.formatter,
)
)
formfield(
'wcd-geo-db:dal:admin:autocomplete:localities',
YourCustomModel.divisions_many_to_many_field,
preparator=DivisionsPreparator(
client=client.bank.divisions,
formatter_client=client.addresses.formatter,
),
# Same as above, but since this is a many-to-many field there have to
# be some adjustments made:
# Many to many field class, that uses preparator to display selected values:
field_class=PreparableModelMultipleChoiceField,
# Widget to display multiselect:
widget_class=ModelSelect2Multiple,
)
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.1.15]
Added
- Slug field
label
added. Added ability to filter overlabel
field. - Division name prefixes. They also used in address formatter now.
- New dumping script. It creates updatable dump.
Changed
- Changed the way geometry data stored. Separate geometry model is there still, but it's deprecated.
- Changed polygon field to be MultiPolygon instead on Polygon.
[0.1.14]
Fixed
- Fixed tree lookups.
Added
- DAL admin extends the default one with fields and filters for division.
[0.1.13]
Fixed
- Fixed setup.
[0.1.12]
Added
- DAL contrib module.
- Small changes to a search mechanics.
[0.1.11]
Fixed
-
Fixed address formatter usage with translations.
If there is none - fallbacks to an original entity data.
Make at least 1, at most 2 queries, no matter the amount of address definitions passed.
[0.1.10]
Fixed
- Translations mechanics added. No changes to an external API. Now it just works as expected.
[0.1.9]
Fixed
- Search fix. Added indexes to improve search performance. Some additional tests added.
Changed
- Search API extended: now you can add a
min_rank
(minimal matching rank 0..1) parameter info asearch_query
to limit matches amount.
[0.1.8]
Added
- Search mechanics implemented. Old API was a little bit changed: language parameter is not required not. Example in README.
[0.1.6]
Fixed
- Tree structure is now optimal.
[0.1.5]
Changed
- Data structure changes.
[0.1.2]
Initial version.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.