A Python package containing Zambian provinces, cities, and constituencies data
Project description
Zambia Geo
A Python package containing Zambian provinces and cities data.
Features
- List all Zambian provinces
- Get cities for each province
- Search for cities
- Validate province and city names
New in v0.2.0: Constituencies
You can now fetch constituencies for each province or district:
from zambia_geo import get_constituencies
Get constituencies for a specific province
constituencies = get_constituencies("Southern") for c in constituencies: print(c.name)
Install in Development Mode Locally
-
Create a virtual environment:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate -
Install the package in development mode:
git clone https://github.com/sangwani-coder/zambia_geo.git cd zambia_geo pip install -e . -
Run Tests
python3 -m pytest tests/
Alternative Installation Methods
Installation in a Project - Force Install
pip install --force-reinstall git+https://github.com/sangwani-coder/zambia_geo.git
Download the ZIP and install
wget https://github.com/sangwani-coder/zambia_geo/archive/main.zip
pip install main.zip
Now you can import and use the package in your Python code:
from zambia_geo import get_all_provinces, get_province_cities
# Get all provinces
provinces = get_all_provinces()
for province in provinces:
print(province.name, province.capital)
# Get cities in a province
cities = get_province_cities("Lusaka")
for city in cities:
print(city.name, city.population)
Usage in Django
To use zambia_geo package in Django model choice fields, you'll need to create choices tuples from the package's data. Here's how you can implement this:
Example Django Model Usage
from django.db import models
from zambia_geo.utils import get_province_choices, get_city_choices
class UserProfile(models.Model):
# Province field
province = models.CharField(
max_length=50,
choices=get_province_choices(),
blank=True,
null=True
)
# City field that depends on province
city = models.CharField(
max_length=50,
choices=[],
blank=True,
null=True
)
class Meta:
verbose_name = "User Profile"
verbose_name_plural = "User Profiles"
def __str__(self):
return f"{self.province} - {self.city}"
Dynamic City Choices Based on Province (Forms)
To make the city choices dynamic based on the selected province, you'll need to use JavaScript or Django's form facilities:
Step 1: Using Django Forms with JavaScript:
# forms.py
from django import forms
from .models import UserProfile
from zambia_geo.utils import get_province_choices, get_city_choices
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['province', 'city']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['province'].choices = [('', 'Select Province')] + get_province_choices()
self.fields['city'].choices = [('', 'Select City')]
# Set initial city choices if province is already selected
if self.instance and self.instance.province:
self.fields['city'].choices = [('', 'Select City')] + get_city_choices(self.instance.province)
Step 2: Create a View to handle Ajax Request
# views.py
from django.http import JsonResponse
from zambia_geo.utils import get_city_choices
def load_cities(request):
province = request.GET.get('province')
if province:
cities = get_city_choices(province)
return JsonResponse({'cities': cities})
return JsonResponse({'cities': []})
Add URL Patten
# urls.py
from django.urls import path
from .views import load_cities
urlpatterns = [
path('load-cities/', load_cities, name='load_cities'),
# other paths...
]
In your template
# admin.py
<!-- Include jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<form method="post" id="profileForm">
{% csrf_token %}
<div class="form-group">
{{ form.province.label_tag }}
{{ form.province }}
</div>
<div class="form-group">
{{ form.city.label_tag }}
{{ form.city }}
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
<script>
$(document).ready(function() {
// When province changes
$('#id_province').change(function() {
var provinceId = $(this).val();
var url = "{% url 'load_cities' %}";
// Clear and disable city dropdown
$('#id_city').html('<option value="">Select City</option>');
if (provinceId) {
// Fetch cities for selected province
$.ajax({
url: url,
data: {
'province': provinceId
},
success: function(data) {
// Populate city dropdown
var options = '<option value="">Select City</option>';
$.each(data.cities, function(index, city) {
options += '<option value="' + city[0] + '">' + city[1] + '</option>';
});
$('#id_city').html(options);
}
});
}
});
});
</script>
Update your view to Handle your Form
# views.py
from django.shortcuts import render, redirect
from .forms import UserProfileForm
def profile_view(request):
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid():
form.save()
return redirect('success_url')
else:
form = UserProfileForm(instance=request.user.profile)
return render(request, 'profile_form.html', {'form': form})
Usage in Flask
flask_zambia_app/
├── app.py
├── templates/
│ └── index.html
└── requirements.txt
Flask Application Code:
# app.py
from flask import Flask, render_template, request, jsonify
from zambia_geo.utils import get_province_choices, get_city_choices
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# Process form submission
province = request.form.get('province')
city = request.form.get('city')
return f"Selected: {province} Province, {city} City"
# GET request - show the form
provinces = get_province_choices()
return render_template('index.html', provinces=provinces)
@app.route('/get_cities')
def get_cities():
province = request.args.get('province')
if province:
cities = get_city_choices(province)
return jsonify({'cities': cities})
return jsonify({'cities': []})
if __name__ == '__main__':
app.run(debug=True)
Template File:
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Zambia Provinces and Cities</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
.form-group { margin-bottom: 15px; }
select { padding: 8px; width: 300px; }
</style>
</head>
<body>
<h1>Select Location in Zambia</h1>
<form method="POST">
<div class="form-group">
<label for="province">Province:</label>
<select id="province" name="province" required>
<option value="">Select Province</option>
{% for code, name in provinces %}
<option value="{{ code }}">{{ name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="city">City:</label>
<select id="city" name="city" required disabled>
<option value="">Select City (choose province first)</option>
</select>
</div>
<button type="submit">Submit</button>
</form>
<script>
$(document).ready(function() {
$('#province').change(function() {
var province = $(this).val();
var $citySelect = $('#city');
$citySelect.empty().prop('disabled', true);
if (province) {
$citySelect.append('<option value="">Loading cities...</option>');
$.getJSON('/get_cities', {province: province}, function(data) {
$citySelect.empty().append('<option value="">Select City</option>');
$.each(data.cities, function(index, city) {
$citySelect.append(
$('<option>', {
value: city[0],
text: city[1]
})
);
});
$citySelect.prop('disabled', false);
});
}
});
});
</script>
</body>
</html>
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.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zambia_geo-0.2.0.tar.gz.
File metadata
- Download URL: zambia_geo-0.2.0.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97509803a0e324c1cdcf800fb823762b41f6329ea48d6d138486fc559d38fb9d
|
|
| MD5 |
a95a37b55ea434cf0d0665f3aad131bb
|
|
| BLAKE2b-256 |
4d33a39207552cae1f815abfd24bffb0a451103675effd1eb73fedb6d4a02753
|
File details
Details for the file zambia_geo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: zambia_geo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
772d3d4030b12483987d08a62538978a856b674bb7d2b509d32b5f325eada878
|
|
| MD5 |
b1202ff6951a6e52e756cdafd310826a
|
|
| BLAKE2b-256 |
ea41096f2bb46cb7181a5eba9c4761c109650cc061f7029fb7926b8382cce686
|