-
V.0.2.2 Stable
released this
2026-06-06 16:10:38 +00:00 | 0 commits to main since this release💥 Breaking changes
- Drop DRF and django-filter dependencies. The package no longer ships
django_nepkit.serializers,django_nepkit.ninja, or
django_nepkit.filters. All serialization is now exposed as
framework-agnostic helpers indjango_nepkit.api(see
serialize_nepali_date,serialize_nepali_time,
serialize_nepali_currency,build_localized_payload, etc.). If you
were using the DRFNepaliDateSerializerField/NepaliCurrencySerializerField
or theNepaliDateYearFilter/NepaliDateMonthFilter/ range filters,
write a thin adapter againstdjango_nepkit.api(or just use plain
Django views — see the updatedexample/demo). BaseNepaliBSField.to_pythonandget_prep_valuenow raise
ValidationErroron bad input instead of silently returning
str(value). Code that was relying on the silent passthrough (e.g.
persisting"not-a-date"strings to the DB) will now fail loudly
at the form / save boundary, which is the correct behaviour.format_nepali_currencyandnumber_to_nepali_wordsnow raise
ValueErroron un-parseable input instead of returningstr(value)
/ crashing withIndexErroron negative numbers. Negative numbers
are now rendered as"ऋणात्मक …".
✨ Features
- New
NepaliTimeField(realTimeFieldwith Devanagari digit output,
auto_now/auto_now_addsupport,BS_TIME_FORMATsetting). - New
NepaliTimeWidgetand JS init for client-side time validation. - New
strictflag on everydjango_nepkit.api.serialize_*/
deserialize_*and onto_decimalfor callers that want to opt
into hard validation errors instead of best-effort passthrough. - Admin address-chaining fixed: districts / municipalities are now
filtered on init when a parent value is preselected (e.g. when
editing an existing record). MunicipalitySelectWidgetnow also supportshtmx=Truelike its
district sibling._render_optionsescapes its HTML output viaformat_html/
format_html_join(XSS fix). The implementation now uses an
explicit per-optionformat_htmlcall (noformat_html_join)
so the attribute / text-node escaping contract is visible at the
call site, and a malformed row (missing keys, non-dict) no longer
crashes the view.BaseLocationField.choicesis now a live property that re-evaluates
on every access from the currentnepkit_settings. An explicit
ne=True/ne=Falseconstructor arg pins the language for the
field's lifetime (only the implicit default re-reads the setting).
refresh_choices()is kept as a no-op for backwards compatibility.BaseNepaliBSField._parse_strnow routes through a process-level
lru_cache(2048)(_cached_parse_nepali_date/
_cached_parse_nepali_datetimeindjango_nepkit.utils). Admin
list views that load thousands of rows with the same stored
date strings no longer re-parse them on every row.normalize_addressis now backed by anlru_cache(1024)-decorated
inner function so the heavy_find_location_in_tokenswork runs at
most once per unique address string. The public function still
returns a fresh dict per call so callers can mutate safely.normalize_addressis now backed by anlru_cache(1024)-decorated
inner function so the heavy_find_location_in_tokenswork runs at
most once per unique address string. The public function still
returns a fresh dict per call so callers can mutate safely.- Demo JSON views (
person_api,audited_api,transaction_api)
accept?strict=1to threadstrict=Truethrough the
serialize_nepali_date/serialize_nepali_datetimecalls — handy
for smoke-testing the strict path against live data. NEPKIT_ONESconstantNEGATIVE_PREFIXis now part of the public
API for callers that want to render negative numbers themselves.
🐛 Bug fixes
- TOCTOU on settings —
NepkitSettingsnow re-reads
settings.NEPKITon every attribute access;override_settingsand
setting_changedare honoured. TheBS_*_FORMATconstants are
re-exported via a module-level__getattr__so direct
from django_nepkit.utils import BS_DATE_FORMATre-reads too. - XSS in
_render_options—id/text/ placeholder values
are now HTML-escaped. Fixes a latent reflected/stored XSS sink
reachable from?html=trueand theHX-Request: truepaths. format_nepali_currencyprecision loss — switched fromfloat
toDecimalend-to-end.Decimal("123456789012345.67")now
formats as"Rs. 1,23,45,67,89,01,234.57"instead of truncated
float garbage.format_nepali_currencynon-finite rejection —inf/nan
/"1e1000"now raiseValueErrorinstead of producing"inf".number_to_nepali_wordsnegative crash — negative numbers
now render with the"ऋणात्मक"prefix instead of raising
IndexError.pyproject.tomlstale version — bumped to0.2.2to match
the release this changelog documents.NepaliDatePickerWidget.format_valueEN-mode leak — passing a
nepalidatein English mode no longer leaks its Python repr
("nepalidate(2081, 1, 15)") into the rendered HTML; unknown
value types render as"".NepaliTimeWidget.format_valueEN-mode leak — same fix for
time values._parse_language_paramssilent coercion —?ne=banananow
falls back to the project default instead of silently returning
False; withstrict=Trueit raisesValueError._get_primary_paramambiguous fallback — when the URL has
multiple non-internal params, the named parameter takes priority
and the "first non-internal" fallback is skipped.address-chaining.jschange-event storm — the init path no
longer fires syntheticchangeevents, so user-defined change
handlers don't run during page load.nepali-time-init.jsMutationObserver flood — added the same
filter (only onform/.nepkit-time-inputadditions) and 50ms
debounce used inaddress-chaining.js, so the time input no
longer triggers an O(document)initAll()on every DOM mutation._make_nepali_time_displayoverriding explicitne=False—
the admin time-display helper used to call
nepkit_settings.DEFAULT_LANGUAGEwhenever_get_field_ne_setting
returnedFalse, which silently overwrote a field-level
NepaliTimeField(ne=False). The helper now returnsNonefor
"no opinion" so the field-level value (including an explicit
False) is preserved.forms.NepaliDateFormFieldexcept Exception:— narrowed
to(ValueError, TypeError, FormatNotMatchException)so genuine
bugs (e.g. aMemoryErrorfrom a runaway parse) are no longer
silently converted into a user-friendlyValidationError.address-chaining.jsMutationObserver scope — the observer
now only triggers init on additions ofform/
.nepkit-province-select/.nepkit-district-selectinstead of
every DOM mutation.address-chaining.jssilent fetch failure — server errors are
now logged viaconsole.errorinstead of swallowed silently.nepali-time-init.jsinvalid-state styling — the
.nepkit-time-invalidclass now ships with default CSS (red
border + soft red background).nepali-time-init.jsNepali-digit input —०१:००is now
normalised to ASCII before regex matching.- Address normalisation fuzzy match —
_find_location_in_tokens
now ranks candidates (exact > substring) so"Pokhara"no longer
loses to"Pokhara Metropolitan City"(or vice versa) for the
same token. - Exception narrowing —
_try_parse_nepali/
try_parse_nepali_timenow catchnepali.exceptions.FormatNotMatchException
explicitly instead of relying on it happening to be aValueError. - Admin
except Exception: pass— replaced with narrow
except (FieldDoesNotExist, AttributeError)so genuine bugs
surface instead of being swallowed. NoReverseMatchswallowed in widgets — the missing-URL case
is now logged at WARNING with a hint pointing at the URLconf.- Demo API input validation —
?order=…,?year=…,?month=…,
?amount_range=…and?date_range=…all return 400 on bad input
(out-of-range month, non-numeric range, unknown order field, …)
instead of 500-ing the request. Accept-Languagefallback — the demo's_ne_flagnow
honoursAccept-Language: nein addition to?ne=true.
♻️ Refactoring
- Extracted framework-agnostic serialization logic into
django_nepkit.api(the only public serialization surface). NepaliDatePickerWidget._configure_attrsnow chains tosuper().__init__.pyis now safe to import with no extra packages
installed, and re-exportsnepkit_settingsfor live access.NepkitSettingsre-readssettings.NEPKITon every access
(sooverride_settingsfinally works) and refuses attribute
assignment (it's read-only — changesettings.NEPKITinstead).BaseNepaliBSField.format_stris now a@propertyso it
re-reads the currentBS_DATE_FORMAT/BS_DATETIME_FORMAT
setting at call time.BaseNepaliBSField.pre_saveshared helper factored out; the
date / datetime subclasses no longer duplicate the TZ
normalization logic._render_optionsescapes its HTML output (fixes latent XSS
sink) and now usesformat_html_join.format_nepali_date/format_nepali_datetimeexposed in
django_nepkit.utils(previously onlyformat_nepali_timewas
available there).
Full Changelog: https://github.com/S4NKALP/django-nepkit/compare/v.0.2.1...v.2.0
Downloads
- Drop DRF and django-filter dependencies. The package no longer ships