175 lines
4.6 KiB
Python
175 lines
4.6 KiB
Python
from django.contrib import admin
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from nepali.datetime import nepalidate, nepalidatetime
|
|
|
|
from django_nepkit.models import NepaliDateField
|
|
|
|
|
|
# --------------------------------------------------
|
|
# Internal helpers
|
|
# --------------------------------------------------
|
|
|
|
def _parse_nepali_date(value):
|
|
"""
|
|
Normalize string / nepalidate to nepalidate.
|
|
"""
|
|
if value is None:
|
|
return None
|
|
|
|
if isinstance(value, nepalidate):
|
|
return value
|
|
|
|
if isinstance(value, str):
|
|
try:
|
|
return nepalidate.strptime(value, "%Y-%m-%d")
|
|
except (ValueError, TypeError):
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
def _parse_nepali_datetime(value):
|
|
"""
|
|
Normalize string / nepalidatetime to nepalidatetime.
|
|
"""
|
|
if value is None:
|
|
return None
|
|
|
|
if isinstance(value, nepalidatetime):
|
|
return value
|
|
|
|
if isinstance(value, str):
|
|
try:
|
|
return nepalidatetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
|
except (ValueError, TypeError):
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
# --------------------------------------------------
|
|
# Formatting helpers
|
|
# --------------------------------------------------
|
|
|
|
def format_nepali_date(value, format_string="%B %d, %Y"):
|
|
"""
|
|
Format a Nepali (BS) date with Nepali month names.
|
|
"""
|
|
nd = _parse_nepali_date(value)
|
|
return nd.strftime(format_string) if nd else ""
|
|
|
|
|
|
def format_nepali_datetime(value, format_string="%B %d, %Y %I:%M %p"):
|
|
"""
|
|
Format a Nepali (BS) datetime (12-hour format by default).
|
|
"""
|
|
ndt = _parse_nepali_datetime(value)
|
|
return ndt.strftime(format_string) if ndt else ""
|
|
|
|
|
|
# --------------------------------------------------
|
|
# Admin List Filter (BS Year)
|
|
# --------------------------------------------------
|
|
|
|
class NepaliDateFilter(admin.FieldListFilter):
|
|
"""
|
|
Admin list filter for NepaliDateField by BS year.
|
|
"""
|
|
|
|
title = _("Nepali Date (Year)")
|
|
|
|
def __init__(self, field, request, params, model, model_admin, field_path):
|
|
self.field_path = field_path
|
|
self.parameter_name = f"{field_path}_bs_year"
|
|
super().__init__(field, request, params, model, model_admin, field_path)
|
|
|
|
def expected_parameters(self):
|
|
return [self.parameter_name]
|
|
|
|
def _year_choices(self):
|
|
current_year = nepalidate.today().year
|
|
return range(current_year - 10, current_year + 2)
|
|
|
|
def choices(self, changelist):
|
|
yield {
|
|
"selected": self.parameter_name not in self.used_parameters,
|
|
"query_string": changelist.get_query_string(remove=[self.parameter_name]),
|
|
"display": _("All"),
|
|
}
|
|
|
|
for year in self._year_choices():
|
|
yield {
|
|
"selected": self.used_parameters.get(self.parameter_name) == str(year),
|
|
"query_string": changelist.get_query_string(
|
|
{self.parameter_name: year}
|
|
),
|
|
"display": year,
|
|
}
|
|
|
|
def queryset(self, request, queryset):
|
|
value = self.used_parameters.get(self.parameter_name)
|
|
if not value:
|
|
return queryset
|
|
|
|
try:
|
|
year = int(value)
|
|
except (TypeError, ValueError):
|
|
return queryset
|
|
|
|
start_bs = nepalidate(year, 1, 1)
|
|
|
|
# BS year length varies (30/31 days)
|
|
for last_day in (31, 30):
|
|
try:
|
|
end_bs = nepalidate(year, 12, last_day)
|
|
break
|
|
except ValueError:
|
|
continue
|
|
|
|
return queryset.filter(
|
|
**{
|
|
f"{self.field_path}__range": (
|
|
start_bs.to_date(),
|
|
end_bs.to_date(),
|
|
)
|
|
}
|
|
)
|
|
|
|
|
|
# Register filter automatically for NepaliDateField
|
|
admin.FieldListFilter.register(
|
|
lambda f: isinstance(f, NepaliDateField),
|
|
NepaliDateFilter,
|
|
take_priority=True,
|
|
)
|
|
|
|
|
|
# --------------------------------------------------
|
|
# Admin mixins
|
|
# --------------------------------------------------
|
|
|
|
class NepaliAdminMixin:
|
|
"""
|
|
Adds Nepali date formatting helpers to admin classes.
|
|
"""
|
|
|
|
format_nepali_date = staticmethod(format_nepali_date)
|
|
format_nepali_datetime = staticmethod(format_nepali_datetime)
|
|
|
|
|
|
class NepaliModelAdmin(NepaliAdminMixin, admin.ModelAdmin):
|
|
"""
|
|
Base ModelAdmin with Nepali utilities.
|
|
|
|
Example:
|
|
@admin.register(MyModel)
|
|
class MyModelAdmin(NepaliModelAdmin):
|
|
list_filter = (('date_bs', NepaliDateFilter),)
|
|
|
|
def date_display(self, obj):
|
|
return self.format_nepali_date(obj.date_bs)
|
|
"""
|
|
|
|
NepaliDateFilter = NepaliDateFilter
|