Package: wc-django-geo-db
WebCase Geographical databaseInstallationpipinstallwc-django-geo-dbInsettings.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',)}Usagefromwcd_geo_db.clientimportGeoClientfromwcd_geo_db.confimportSettingsfromwcd_geo_db.modules.code_seekerimportregistryfromwcd_geo_db_sources.sources.koatuuimportKOATUU_SEEKERfromwcd_geo_db_sources.sources.katottgimportKATOTTG_SEEKERfromwcd_geo_db_sources.sources.novaposhtaimportNOVAPOSHTA_SEEKERclient=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 resolveSince [0.1.15].You may now choose in what variation you can retrieve your data.There is only 2 options right now:asDivisionDTO- It's simple, but provide all the data you need for regular use. Used by default.asExtendedDivisionDTO- Provides additional geography info(location, polygon) and prefix name definition.fromwcd_geo_db.modules.bank.dtosimportDivisionDTO,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 formatteraddress=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 onefallback_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.Searchingsearch=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].Addeduse_simple_searchparameter to divisions search. It forces search mechanics to use simple__icontainsinstead 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',})ContribDALSince [0.1.12].To use django autocomplete light you need to install library with[dal]extras.Like so:pipinstallwc-django-geo-db[dal]UrlsDefault autocomplete urls could be made as:# Importing url factory.fromwcd_geo_db.contrib.dal.urlsimportmake_urlpatterns# Importing defined GeoClient instance somewhere from your project:fromyour_project.geo_clientimportclienturlpatterns=[# 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:fromdjango.urlsimportpath,includefromwcd_geo_db.constimportDivisionLevelfromwcd_geo_db.contrib.dal.urlsimportmake_urlpatterns,make_divisions_path,autocomplete_namespacefromwcd_geo_db.contrib.dal.viewsimportDivisionDalViewAdminfromyour_project.geo_clientimportclienturlpatterns=[# 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 integrationTo use autocomplete urls in admin you may do something like this:your_application/admin.pyfromdal_select2.widgetsimportModelSelect2Multiplefromwcd_geo_db.contrib.dal.djhackerimportformfieldfromwcd_geo_db.contrib.dal.formsimportPreparableModelMultipleChoiceFieldfromwcd_geo_db.contrib.dal.preparatorsimportDivisionsPreparatorfromyour_project.geo_clientimportclientfrom.modelsimportYourCustomModel# 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,)ChangelogAll notable changes to this project will be documented in this file.The format is based onKeep a Changelog,
and this project adheres toSemantic Versioning.[Unreleased][0.1.15]AddedSlug fieldlabeladded. Added ability to filter overlabelfield.Division name prefixes. They also used in address formatter now.New dumping script. It creates updatable dump.ChangedChanged 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]FixedFixed tree lookups.AddedDAL admin extends the default one with fields and filters for division.[0.1.13]FixedFixed setup.[0.1.12]AddedDAL contrib module.Small changes to a search mechanics.[0.1.11]FixedFixed 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]FixedTranslations mechanics added. No changes to an external API. Now it just works as expected.[0.1.9]FixedSearch fix. Added indexes to improve search performance. Some additional tests added.ChangedSearch API extended: now you can add amin_rank(minimal matching rank 0..1) parameter info asearch_queryto limit matches amount.[0.1.8]AddedSearch mechanics implemented. Old API was a little bit changed: language parameter is not required not. Example in README.[0.1.6]FixedTree structure is now optimal.[0.1.5]ChangedData structure changes.[0.1.2]Initial version.