Skip to content

Commit 19df01b

Browse files
first commit
0 parents  commit 19df01b

File tree

10 files changed

+560
-0
lines changed

10 files changed

+560
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.pytest_cache
2+
.env
3+
__pycache__
4+
*.pyc
5+
*.pyo
6+
*.pyd
7+
*.db
8+
*.sqlite3
9+
*.log

README.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Zambia Geo
2+
3+
A Python package containing Zambian provinces and cities data.
4+
5+
## Features
6+
7+
* List all Zambian provinces
8+
* Get cities for each province
9+
* Search for cities
10+
* Validate province and city names
11+
12+
## How to Use Locally
13+
14+
1. Create a virtual environment:
15+
```bash```
16+
17+
python -m venv venv
18+
source venv/bin/activate # On Windows: venv\Scripts\activate
19+
20+
2. Install the package in development mode:
21+
22+
pip install -e .
23+
24+
3. Run Tests
25+
26+
python -m pytest tests/
27+
28+
### Now you can import and use the package in your Python code:
29+
30+
from zambia_geo import get_all_provinces, get_province_cities
31+
# Get all provinces
32+
provinces = get_all_provinces()
33+
for province in provinces:
34+
print(province.name, province.capital)
35+
36+
# Get cities in a province
37+
cities = get_province_cities("Lusaka")
38+
for city in cities:
39+
print(city.name, city.population)
40+
41+
## Usage in Django
42+
43+
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:
44+
45+
### Example Django Model Usage
46+
47+
from django.db import models
48+
from zambia_geo.utils import get_province_choices, get_city_choices
49+
50+
class UserProfile(models.Model):
51+
# Province field
52+
province = models.CharField(
53+
max_length=50,
54+
choices=get_province_choices(),
55+
blank=True,
56+
null=True
57+
)
58+
59+
# City field that depends on province
60+
city = models.CharField(
61+
max_length=50,
62+
choices=[],
63+
blank=True,
64+
null=True
65+
)
66+
67+
class Meta:
68+
verbose_name = "User Profile"
69+
verbose_name_plural = "User Profiles"
70+
71+
def __str__(self):
72+
return f"{self.province} - {self.city}"
73+
74+
## Dynamic City Choices Based on Province (Forms)
75+
76+
To make the city choices dynamic based on the selected province, you'll need to use JavaScript or Django's form facilities:
77+
78+
**Option 1: Using Django Forms with JavaScript:**
79+
80+
# forms.py
81+
from django import forms
82+
from .models import UserProfile
83+
from zambia_geo.utils import get_province_choices
84+
85+
class UserProfileForm(forms.ModelForm):
86+
class Meta:
87+
model = UserProfile
88+
fields = ['province', 'city']
89+
90+
def __init__(self, *args, **kwargs):
91+
super().__init__(*args, **kwargs)
92+
self.fields['province'].choices = get_province_choices()
93+
self.fields['city'].choices = []
94+
95+
if 'province' in self.data:
96+
try:
97+
province_name = self.data.get('province')
98+
self.fields['city'].choices = get_city_choices(province_name)
99+
except (ValueError, TypeError):
100+
pass
101+
elif self.instance.pk and self.instance.province:
102+
self.fields['city'].choices = get_city_choices(self.instance.province)
103+
104+
**Option 2: JavaScript Implementation:**
105+
106+
If you prefer a pure JavaScript solution, here's how to implement it:
107+
108+
<!-- In your template -->
109+
<form method="post">
110+
{% csrf_token %}
111+
112+
<div class="form-group">
113+
<label for="province">Province</label>
114+
<select class="form-control" id="province" name="province">
115+
<option value="">Select Province</option>
116+
{% for value, label in province_choices %}
117+
<option value="{{ value }}" {% if value == selected_province %}selected{% endif %}>{{ label }}</option>
118+
{% endfor %}
119+
</select>
120+
</div>
121+
122+
<div class="form-group">
123+
<label for="city">City</label>
124+
<select class="form-control" id="city" name="city">
125+
<option value="">Select City</option>
126+
{% for value, label in city_choices %}
127+
<option value="{{ value }}" {% if value == selected_city %}selected{% endif %}>{{ label }}</option>
128+
{% endfor %}
129+
</select>
130+
</div>
131+
132+
<button type="submit" class="btn btn-primary">Submit</button>
133+
</form>
134+
135+
<script>
136+
document.getElementById('province').addEventListener('change', function() {
137+
const province = this.value;
138+
const citySelect = document.getElementById('city');
139+
140+
// Clear existing options
141+
citySelect.innerHTML = '<option value="">Select City</option>';
142+
143+
if (province) {
144+
// Fetch cities for the selected province
145+
fetch(`/api/cities/?province=${province}`)
146+
.then(response => response.json())
147+
.then(data => {
148+
data.cities.forEach(city => {
149+
const option = document.createElement('option');
150+
option.value = city.name;
151+
option.textContent = city.name;
152+
citySelect.appendChild(option);
153+
});
154+
});
155+
}
156+
});
157+
</script>
158+
159+
### Create an API endpoint for cities (optional)
160+
161+
# views.py
162+
from django.http import JsonResponse
163+
from zambia_geo import get_province_cities
164+
165+
def get_cities(request):
166+
province = request.GET.get('province')
167+
if province:
168+
cities = get_province_cities(province)
169+
cities_data = [{'name': city.name} for city in cities]
170+
return JsonResponse({'cities': cities_data})
171+
return JsonResponse({'cities': []})
172+
173+
# urls.py
174+
from django.urls import path
175+
from .views import get_cities
176+
177+
urlpatterns = [
178+
path('api/cities/', get_cities, name='get_cities'),
179+
# other URLs...
180+
]
181+
182+
### Admin Integration
183+
To use these choices in Django admin:
184+
185+
# admin.py
186+
from django.contrib import admin
187+
from .models import UserProfile
188+
from zambia_geo.utils import get_province_choices, get_city_choices
189+
190+
class UserProfileAdmin(admin.ModelAdmin):
191+
list_display = ('province', 'city')
192+
193+
def get_form(self, request, obj=None, **kwargs):
194+
form = super().get_form(request, obj, **kwargs)
195+
form.base_fields['province'].choices = get_province_choices()
196+
197+
if obj and obj.province:
198+
form.base_fields['city'].choices = get_city_choices(obj.province)
199+
else:
200+
form.base_fields['city'].choices = []
201+
202+
return form
203+
204+
admin.site.register(UserProfile, UserProfileAdmin)

__init__.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
A Python package containing Zambian provinces and cities data.
3+
4+
This package provides easy access to geographical data about Zambia,
5+
including all provinces and their major cities/towns.
6+
"""
7+
8+
from .data import (
9+
get_all_provinces,
10+
get_province_cities,
11+
get_city_details,
12+
search_cities,
13+
get_all_cities,
14+
validate_province,
15+
validate_city
16+
)
17+
18+
from .models import Province, City
19+
20+
__version__ = "0.1.0"
21+
__all__ = [
22+
'get_all_provinces',
23+
'get_province_cities',
24+
'get_city_details',
25+
'search_cities',
26+
'get_all_cities',
27+
'validate_province',
28+
'validate_city',
29+
'Province',
30+
'City'
31+
]

0 commit comments

Comments
 (0)