🌍 GeoBank
A comprehensive Django package for countries, regions, and cities with full translation support
GeoBank provides ready-to-use Django models for geographic data including countries, regions/states, and cities with built-in translation support using django-modeltranslation. It fetches data from trusted sources like GeoNames and REST Countries.
✨ Features
-
🗺️ Comprehensive Geographic Data
- 250+ countries with detailed information
- 4,000+ regions/states/provinces
- 20,000+ cities (configurable population threshold)
-
🌐 Rich Country Information
- ISO Alpha-2 and Alpha-3 codes
- Continent classification
- Population data
- Currency with symbol
- Multiple calling codes
- Official languages
- Neighboring countries
- Flag images (PNG & SVG)
- Postal code format and regex
- Top-level domain (TLD)
-
🏙️ Detailed City Data
- Geographic coordinates (latitude/longitude)
- Timezone information
- Population statistics
- Region/state association
-
🔤 Full Translation Support
- Powered by
django-modeltranslation - Translate country, region, and city names
- Support for any language
- Powered by
-
⚡ Performance Optimized
- Bulk database operations
- Efficient data parsing
- Background task support via Celery
-
🧪 Well Tested
- Comprehensive unit tests
- Full integration tests
- CI/CD with GitHub Actions
📦 Installation
pip install GeoBank
🚀 Quick Start
1. Configure Django Settings
Add geobank and modeltranslation to your INSTALLED_APPS:
⚠️ Important:
modeltranslationmust be added beforedjango.contrib.admin
INSTALLED_APPS = [
'modeltranslation', # Must be before admin
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# ...
'geobank',
]
2. Configure Languages
Set up the languages you want to support:
LANGUAGES = (
('en', 'English'),
('es', 'Spanish'),
('fr', 'French'),
('de', 'German'),
('ar', 'Arabic'),
('zh', 'Chinese'),
# Add more languages as needed
)
MODELTRANSLATION_DEFAULT_LANGUAGE = 'en'
3. Run Migrations
python manage.py makemigrations
python manage.py migrate
4. Populate the Database
python manage.py populate_geobank
That's it! 🎉 Your database is now populated with geographic data.
📖 Usage
Basic Queries
from geobank.models import Country, Region, City
# Get all countries
countries = Country.objects.all()
# Get a specific country
usa = Country.objects.get(code2='US')
print(usa.name) # "United States"
print(usa.code3) # "USA"
print(usa.population) # 331002651
print(usa.currency.code) # "USD"
print(usa.currency.symbol) # "$"
# Get country's calling codes
for calling_code in usa.calling_codes.all():
print(calling_code.code) # "1"
# Get country's languages
for language in usa.languages.all():
print(language.name) # "English"
# Get neighboring countries
for neighbor in usa.neighbors.all():
print(neighbor.name) # "Canada", "Mexico"
# Get regions/states
california = Region.objects.get(country=usa, code='CA')
print(california.name) # "California"
# Get cities
la = City.objects.get(name='Los Angeles', country=usa)
print(la.population) # 3979576
print(la.timezone) # "America/Los_Angeles"
print(la.latitude, la.longitude) # Coordinates
Working with Translations
from django.utils.translation import activate
# Get country name in different languages
usa = Country.objects.get(code2='US')
activate('en')
print(usa.name) # "United States"
activate('es')
print(usa.name) # "Estados Unidos"
activate('ar')
print(usa.name) # "الولايات المتحدة"
Filtering
# Countries by continent
european_countries = Country.objects.filter(continent='EU')
# Cities by population
large_cities = City.objects.filter(population__gte=1000000)
# Cities in a region
california_cities = City.objects.filter(region__code='CA', country__code2='US')
# Active records only
active_countries = Country.objects.filter(is_active=True)
Using Flags
usa = Country.objects.get(code2='US')
# Flag URLs from REST Countries
print(usa.flag_png) # PNG URL
print(usa.flag_svg) # SVG URL
⚙️ Configuration Options
Population Command Options
# Basic population (cities with 15,000+ population)
python manage.py populate_geobank
# Include smaller cities (500, 1000, 5000, or 15000)
python manage.py populate_geobank --population-gte 5000
# Run in background with Celery
python manage.py populate_geobank --background
City Population Thresholds
| Option | Cities Count | Description |
|---|---|---|
15000 |
~25,000 | Major cities only (default) |
5000 |
~50,000 | Medium-sized cities |
1000 |
~140,000 | Small cities included |
500 |
~200,000 | All significant settlements |
📊 Models Reference
Country
| Field | Type | Description |
|---|---|---|
name |
CharField | Country name (translatable) |
name_ascii |
CharField | ASCII-safe name |
slug |
AutoSlugField | URL-friendly slug |
code2 |
CharField | ISO 3166-1 alpha-2 code |
code3 |
CharField | ISO 3166-1 alpha-3 code |
fips |
CharField | FIPS code |
continent |
CharField | Continent code (AF, AS, EU, NA, OC, SA, AN) |
tld |
CharField | Top-level domain |
population |
BigIntegerField | Population count |
currency |
ForeignKey | Related Currency |
languages |
ManyToManyField | Related Languages |
neighbors |
ManyToManyField | Neighboring countries |
flag_png |
URLField | Flag image (PNG) |
flag_svg |
URLField | Flag image (SVG) |
postal_code_format |
CharField | Postal code format |
postal_code_regex |
CharField | Postal code validation regex |
is_active |
BooleanField | Active status |
Region
| Field | Type | Description |
|---|---|---|
name |
CharField | Region name (translatable) |
name_ascii |
CharField | ASCII-safe name |
slug |
AutoSlugField | URL-friendly slug |
code |
CharField | Region code |
country |
ForeignKey | Related Country |
geoname_id |
IntegerField | GeoNames ID |
is_active |
BooleanField | Active status |
City
| Field | Type | Description |
|---|---|---|
name |
CharField | City name (translatable) |
name_ascii |
CharField | ASCII-safe name |
slug |
AutoSlugField | URL-friendly slug |
country |
ForeignKey | Related Country |
region |
ForeignKey | Related Region |
latitude |
DecimalField | Latitude coordinate |
longitude |
DecimalField | Longitude coordinate |
population |
BigIntegerField | Population count |
timezone |
CharField | Timezone identifier |
geoname_id |
IntegerField | GeoNames ID |
is_active |
BooleanField | Active status |
Currency
| Field | Type | Description |
|---|---|---|
code |
CharField | ISO 4217 code (e.g., USD) |
name |
CharField | Currency name |
symbol |
CharField | Currency symbol |
is_active |
BooleanField | Active status |
Language
| Field | Type | Description |
|---|---|---|
code |
CharField | ISO 639-2 code (3-letter) |
code2 |
CharField | ISO 639-1 code (2-letter) |
name |
CharField | Language name |
is_active |
BooleanField | Active status |
CallingCode
| Field | Type | Description |
|---|---|---|
country |
ForeignKey | Related Country |
code |
CharField | Calling code (e.g., "1" for USA) |
🔧 Requirements
| Package | Version |
|---|---|
| Python | >= 3.8 |
| Django | >= 3.2 |
| django-modeltranslation | >= 0.18.0 |
| Pillow | >= 9.0 |
| django-autoslug | >= 1.9 |
| Celery | >= 5.0 (optional) |
🧪 Development
Setting Up Development Environment
# Clone the repository
git clone https://github.com/ali-hv/geobank.git
cd geobank
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install with dev dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pip install pre-commit
pre-commit install
Running Tests
# Run unit tests only (fast)
pytest src/geobank/tests/ -m "not integration" -v
# Run integration tests (requires network, slower)
pytest src/geobank/tests/ -m "integration" -v
# Run all tests
pytest src/geobank/tests/ -v
# Run with coverage
pytest src/geobank/tests/ --cov=geobank --cov-report=html
Code Quality
# Run linter
ruff check src/
# Run formatter
ruff format src/
# Run pre-commit on all files
pre-commit run --all-files
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Geographic data from GeoNames
- Country information from REST Countries
- Translation support by django-modeltranslation
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Metadata
Release files for GeoBank 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geobank-1.1.1.tar.gz | 29.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| geobank-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.7 kB
Release files / geobank-1.1.1.tar.gz
| Download URL | geobank-1.1.1.tar.gz |
|---|---|
| Size | 29.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c29afa1632fdd7a04555a4335d02540202feef7f47cfcc4467f54a5a5499e17f
|
|
BLAKE2b-256 checksum How to use checksums |
6724a29331a788568ad775f1d698be0ff03640a56400cb44e7152fdad5ed493b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / geobank-1.1.1-py3-none-any.whl
| Download URL | geobank-1.1.1-py3-none-any.whl |
|---|---|
| Size | 35.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
be8e5699959a6933fbea75c7e6aa063e8c36acc2f798881f5b3acebb80fb9469
|
|
BLAKE2b-256 checksum How to use checksums |
63c15b97027d79dc4fb1a9f807d0726a4fd63c55301b15a2de99db86bcada373
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|