Files
django-nepkit/django_nepkit/utils.py
T
sankalp ed93467296 feat: revamp localization support with Devanagari (BS) integration and documentation
Implemented a comprehensive update to handle Nepali (Bikram Sambat) localization more robustly across models, forms, admin, and API serializers. This includes native support for Devanagari script output and a complete documentation overhaul.

Models & Fields:
- Added [NepaliFieldMixin](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:15:0-36:39) to support [ne](cci:1://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:146:4-163:67) (Nepali) and [en](cci:1://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/widgets.py:4:0-10:16) (English) toggles for all custom fields.
- Updated [NepaliDateField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:48:0-134:44), [NepaliDateTimeField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:144:0-217:44), and [NepaliTimeField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:137:0-141:34) with the new mixin and improved deconstruction.
- Enhanced address fields ([ProvinceField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:220:0-262:23), [DistrictField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:265:0-286:66), [MunicipalityField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/models.py:289:0-310:66)) to support bilingual choices.

Admin Enhancements:
- Refactored date formatting into a common utility supporting Devanagari via `strftime_ne`.
- Updated [NepaliModelAdmin](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:186:0-294:9) and [NepaliAdminMixin](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:118:0-183:75) to auto-detect [ne](cci:1://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:146:4-163:67) settings from model fields for [list_display](cci:1://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:230:4-250:21).
- Improved widget injection in the admin to respect field-level localization settings.
- Added a JS bridge for admin jQuery compatibility with the Nepali datepicker.

Forms & Widgets:
- Introduced [NepaliWidgetMixin](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/widgets.py:13:0-38:12) to handle localization data attributes in the frontend.
- Updated [NepaliDatePickerWidget](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/widgets.py:63:0-99:42) with improved asset loading and Devanagari support.
- Fixed [NepaliDateFormField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/forms.py:10:0-41:13) to correctly handle `empty_value` passed by the Django admin.

DRF (Serializers):
- Added [BaseNepaliBSField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/serializers.py:21:0-106:48) to DRF serializers with support for `ne=True` for Devanagari output.
- Implemented specialized [NepaliDateSerializerField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/serializers.py:114:0-122:28) and [NepaliDateTimeSerializerField](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/serializers.py:130:0-138:32).

Documentation:
- Completely revamped [README.md](cci:7://file:///home/sankalp/Projects/prod-django-nepkit/README.md:0:0-0:0) with professional design, badges, and detailed usage guides.
- Added explicit instructions for address chaining URLs and [NepaliAdminMixin](cci:2://file:///home/sankalp/Projects/prod-django-nepkit/django_nepkit/admin.py:118:0-183:75) usage.

Misc:
- Optimized address chaining JS logic.
- Updated example demo app models and migrations to reflect new field capabilities.
2026-01-30 13:32:33 +05:45

80 lines
2.3 KiB
Python

from __future__ import annotations
from typing import Any, Optional
from nepali.datetime import nepalidate, nepalidatetime
from nepali.locations import districts, provinces
BS_DATE_FORMAT = "%Y-%m-%d"
BS_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
def _try_parse_nepali(value: Any, cls: Any, 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):
try:
return cls.strptime(value.strip(), fmt)
except Exception:
return None
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:
if p.name == parent_name or getattr(p, "name_nepali", None) == 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)