- Implement server-side location chaining with HTMX support via `htmx=True` in fields and widgets. - Update location views to handle HTMX requests and return HTML <option> fragments. - Add NepaliDateYearFilter and NepaliDateRangeFilter for robust DRF API filtering. - Expand default `DATE_INPUT_FORMATS` in configuration to support multiple common Nepali date styles. - Update DRF serializers to automatically respect global `NEPKIT` configuration settings. - Add `django-filter` as an optional dependency under the `drf` extra in pyproject.toml. - Correct underlying dependency references from `nepali-datetime` to nepali library. - Complete overhaul of README.md for premium DX, including new sections for storage behavior, timezone awareness, and API usage.
100 lines
3.0 KiB
Python
100 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Optional
|
|
|
|
from nepali.datetime import nepalidate, nepalidatetime
|
|
from nepali.locations import districts, provinces
|
|
|
|
from django_nepkit.conf import nepkit_settings
|
|
|
|
BS_DATE_FORMAT = "%Y-%m-%d"
|
|
BS_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
|
|
|
|
|
def _try_parse_nepali(value: Any, cls: Any, fallback_fmt: str) -> Any:
|
|
"""Internal helper to parse Nepali date/datetime."""
|
|
if value in (None, ""):
|
|
return None
|
|
if isinstance(value, cls):
|
|
return value
|
|
if isinstance(value, str):
|
|
formats = nepkit_settings.DATE_INPUT_FORMATS
|
|
if fallback_fmt not in formats:
|
|
formats = list(formats) + [fallback_fmt]
|
|
|
|
for fmt in formats:
|
|
try:
|
|
return cls.strptime(value.strip(), fmt)
|
|
except Exception:
|
|
continue
|
|
return None
|
|
|
|
|
|
def try_parse_nepali_date(value: Any) -> Optional[nepalidate]:
|
|
"""
|
|
Best-effort conversion to `nepalidate`.
|
|
"""
|
|
return _try_parse_nepali(value, nepalidate, BS_DATE_FORMAT)
|
|
|
|
|
|
def try_parse_nepali_datetime(value: Any) -> Optional[nepalidatetime]:
|
|
"""
|
|
Best-effort conversion to `nepalidatetime`.
|
|
"""
|
|
return _try_parse_nepali(value, nepalidatetime, BS_DATETIME_FORMAT)
|
|
|
|
|
|
def _get_location_children(parent_list, parent_name, child_attr, ne=False):
|
|
"""
|
|
Internal helper to finding a parent in a list and returning its children (districts/municipalities).
|
|
"""
|
|
selected_parent = None
|
|
for p in parent_list:
|
|
p_name = p.name
|
|
p_name_ne = getattr(p, "name_nepali", None)
|
|
|
|
# Mapping fix for lookups
|
|
if parent_name == "Koshi Province":
|
|
if p_name == "Province 1":
|
|
selected_parent = p
|
|
break
|
|
elif parent_name == "कोशी प्रदेश":
|
|
if p_name_ne == "प्रदेश नं. १":
|
|
selected_parent = p
|
|
break
|
|
|
|
if p_name == parent_name or p_name_ne == parent_name:
|
|
selected_parent = p
|
|
break
|
|
|
|
if not selected_parent:
|
|
return []
|
|
|
|
children = getattr(selected_parent, child_attr, [])
|
|
|
|
if ne:
|
|
return [
|
|
{
|
|
"id": getattr(child, "name_nepali", child.name),
|
|
"text": getattr(child, "name_nepali", child.name),
|
|
}
|
|
for child in children
|
|
]
|
|
else:
|
|
return [{"id": child.name, "text": child.name} for child in children]
|
|
|
|
|
|
def get_districts_by_province(province_name, ne=False, en=True):
|
|
"""
|
|
Returns a list of districts in the given province.
|
|
"""
|
|
# Logic note: if ne=True is passed, we shouldn't care about en=True (handled by caller typically)
|
|
return _get_location_children(provinces, province_name, "districts", ne=ne)
|
|
|
|
|
|
def get_municipalities_by_district(district_name, ne=False, en=True):
|
|
"""
|
|
Returns a list of municipalities in the given district.
|
|
"""
|
|
return _get_location_children(districts, district_name, "municipalities", ne=ne)
|