Browse files

- Data pulls from GeoNames and imports directly into database, no fix…


- Downloads and updates only if data has changed
- All ids are same as GeoNames', so updates only overwrite matching ids
- Localized / Alternate names and dynamically created locale models
- Main geo name is now ASCII instead of UTF-8 (better for coding / search)
- The UTF-8 standard name is still available as a fallback if name isn't localized
- Using cities5000 instead of cities1000 (half the size)
- Fast imports using dict index instead of db
- Fixed latitude / longitude mixup
- Full admin interface
- Reduced to one command 'cities' with options
- Cleaned up code and logging
  • Loading branch information...
Qarterd committed Nov 26, 2011
1 parent 991f581 commit 48d2c2e37c0febc436414b441a95925fedd5fbb8
@@ -1 +1,5 @@
No changes.
@@ -1,53 +1,80 @@
django-cities - Place models and data for Django apps
-This project includes country, region, city, and district models and is
-prepopulated with data from GeoNames. The GeoNames import script
-is also included if you'd like to re-import the data yourself, or change
-the way in which it gets cleaned up.
+This add-on provides models and commands to import country / region / city / district data into your database.
+The data is pulled from GeoNames and contains localized names, codes, geo-coords, and population.
-Includes 234 counties, 2,610 regions, 97,949 cities and 606 districts
+Your database must support spatial queries, see GeoDjango for setup.
-For more information and examples see
+For more information see:
Finding all London boroughs:
>>> london = City.objects.filter(country__name='United Kingdom').get(name='London')
>>> boroughs = District.objects.filter(city=london)
-Nearest city to a given lat,lon:
+Nearest city to a given geo-coord (longitude, latitude):
->>> City.objects.nearest_to(51, 1)
+>>> City.objects.distance(Point(1, 51)).order_by('distance')[0]
<City: Dymchurch, Kent, United Kingdom>
5 Nearest cities to London:
>>> london = City.objects.filter(country__name='United Kingdom').get(name='London')
>>> nearest = City.objects.distance(london.location).exclude('distance')[:5]
-Important Notice:
+Get all countries in Japanese preferring official names if available, fallback on ASCII names:
+>>> [country.alt_names_ja.get_preferred( for country in Country.objects.all()]
-The old dump file contained wrong locations (longtitude and latitude upside down, to be precise). The latest dump file fixed this error. Before updating to the latest dump, please read the following changes made to the current release:
+Use alternate names model to get Vancouver in Japanese:
-1. The dump file is renamed from initial_data.json to geonames_dump.json. This means data won't be loaded into databases automatically when running syncdb command. To load the dump, you have to run " loaddata geonames_dump" explicitly, which is actually a good feature since the original name can cause this dump file to be loaded every time you run syncdb command. There are not just only a few records in it, you know...
+>>> geo_alt_names[City]['ja'].objects.get_preferred(geo__name='Vancouver', default='Vancouver')
-2. The dump file has the correct locations now. Distances will be calculated correctly.
+Gather names of Tokyo from all LANGUAGES, including names from undetermined language data ('und'):
-3. A command called load_geonames is added. This command allows you to only load countries you feel needed in your application. Originally, the whole dump is loaded into the database, which might be too overwhelming for you or your database. Now, say you only want data for United States and Canada, run " load_geonames US CA", dada... only districts, cities, regions and countries of these two countries are loaded into the database. Later you decide to add China to the country list, you run " load_geonames CN". Now you have data for three countries.
+>>> [name for locale in settings.CITIES_LOCALES
+ for name in geo_alt_names[City][locale].objects.filter(geo__name='Tokyo')]
-In short, after installing django-cities, add django-cities to your installed app in Then you have two choices:
-1. To import the whole dump, run command:
+- Run: python install
+- Add/Merge the following into your loaddata geonames_dump
+ 'cities',
-2. Choose certain countries to import, run command:
+ 'handlers': {
+ 'console':{
+ 'level':'DEBUG',
+ 'class':'logging.StreamHandler',
+ },
+ },
+ 'loggers': {
+ 'cities': {
+ 'handlers': ['console'],
+ 'level': 'INFO',
+ }
+ }
+} load_geonames [country_code_list]
+if 'LANGUAGES' in locals(): CITIES_LOCALES += [lang[0] for lang in LANGUAGES]
-country_code_list is a list of country codes separated by spaces.
-If you've installed django-cities and imported data before, the first command will fix all the location errors and the second one will fix the location errors of selected countries.
+- Sync your database with the new models: ' syncdb'
+- Populate or update your database by running: ' cities'
+The localized models / tables are created dynamically from CITIES_LOCALES.
+Some datasets are very large (> 100 MB) and take time to download / import, and there's no progress display.
+Data will only be downloaded / imported if it is newer than your data, and only matching rows will be overwritten.
+The cities manage command has options, see --help. Verbosity is controlled through LOGGING.
@@ -1,10 +1,39 @@
from django.contrib import admin
-from models import * #@UnusedWildImport
+from models import *
-class SearchableAdmin(admin.ModelAdmin):
- search_fields = ['name']
+class CountryAdmin(admin.ModelAdmin):
+ list_display = ['name', 'code', 'tld', 'population']
+ search_fields = ['name']
+, CountryAdmin), SearchableAdmin), SearchableAdmin), SearchableAdmin), SearchableAdmin)
+class RegionAdmin(admin.ModelAdmin):
+ ordering = ['name_std']
+ list_display = ['name_std', 'country', 'code']
+ search_fields = ['name', 'name_std']
+, RegionAdmin)
+class CityAdmin(admin.ModelAdmin):
+ ordering = ['name_std']
+ list_display = ['name_std', 'region', 'population']
+ search_fields = ['name', 'name_std']
+, CityAdmin)
+class DistrictAdmin(admin.ModelAdmin):
+ ordering = ['name_std']
+ list_display = ['name_std', 'city', 'population']
+ search_fields = ['name', 'name_std']
+ readonly_fields = ['city'] # City choice list creation is slow
+, DistrictAdmin)
+class GeoAltNameAdmin(admin.ModelAdmin):
+ ordering = ['name']
+ list_display = ['name', 'geo', 'is_preferred', 'is_short']
+ list_filter = ['is_preferred', 'is_short']
+ search_fields = ['name']
+ readonly_fields = ['geo'] # City choice list creation is slow
+[, GeoAltNameAdmin) for locales in geo_alt_names.values() for geo_alt_name in locales.values()]
Oops, something went wrong.

0 comments on commit 48d2c2e

Please sign in to comment.