210 lines
6.9 KiB
Markdown
210 lines
6.9 KiB
Markdown
# 🇳🇵 django-nepkit
|
|
|
|
<div align="center">
|
|
|
|
[](https://badge.fury.io/py/django-nepkit)
|
|
[](https://pypi.org/project/django-nepkit/)
|
|
[](https://www.djangoproject.com/)
|
|
[](https://opensource.org/licenses/MIT)
|
|
|
|
**A toolkit for handling BS dates, regional locations, and validation in the local context.**
|
|
|
|
</div>
|
|
|
|
Building software for local requirements comes with unique challenges—from handling BS dates to managing the regional administrative hierarchy. `django-nepkit` provides solutions for these requirements directly within the Django ecosystem.
|
|
|
|

|
|
|
|
---
|
|
|
|
## 🎯 Features
|
|
|
|
- **📅 BS Date Support**: Model fields for `nepalidate` and `nepalidatetime` objects.
|
|
- **🗺️ Regional Locations**: Pre-defined Provinces, Districts, and Municipalities.
|
|
- **📱 Phone Validation**: Patterns for local mobile and landline numbers.
|
|
- **🔌 Admin Integration**: Automatic setup for datepickers and localized list displays.
|
|
- **🚀 API Support**: DRF Serializers and Filtering backends for BS searching and ordering.
|
|
- **⚡ Location Chaining**: Address linking via client-side JS or server-driven HTMX.
|
|
|
|
---
|
|
|
|
## 🛠 Setup
|
|
|
|
Installation:
|
|
|
|
```bash
|
|
pip install django-nepkit
|
|
```
|
|
|
|
### 1. Basic Configuration
|
|
|
|
Add it to your `INSTALLED_APPS`:
|
|
|
|
```python
|
|
INSTALLED_APPS = [
|
|
# ...
|
|
"django_nepkit",
|
|
]
|
|
```
|
|
|
|
### 2. Global Control
|
|
|
|
Configure behavior in your `settings.py`:
|
|
|
|
```python
|
|
NEPKIT = {
|
|
"DEFAULT_LANGUAGE": "en", # "en" or "ne"
|
|
"ADMIN_DATEPICKER": True, # Toggle the datepicker
|
|
"TIME_FORMAT": 12, # 12 or 24 hour display
|
|
"DATE_INPUT_FORMATS": ["%Y-%m-%d", "%d/%m/%Y", "%d-%m-%Y"], # Input formats
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Core Usage
|
|
|
|
### 1. Model Implementation
|
|
|
|
Fields store `YYYY-MM-DD` strings for database stability while providing BS objects in Python.
|
|
|
|
```python
|
|
from django_nepkit import NepaliDateField, NepaliPhoneNumberField
|
|
|
|
class Profile(models.Model):
|
|
name = models.CharField(max_length=100)
|
|
birth_date = NepaliDateField() # BS Date support
|
|
phone = NepaliPhoneNumberField() # Local pattern validation
|
|
```
|
|
|
|
### 2. Admin Integration
|
|
|
|
Use `NepaliModelAdmin` for automatic formatting and datepicker support.
|
|
|
|
```python
|
|
from django_nepkit import NepaliModelAdmin, NepaliDateFilter
|
|
|
|
@admin.register(Profile)
|
|
class ProfileAdmin(NepaliModelAdmin):
|
|
list_display = ("name", "birth_date", "phone")
|
|
list_filter = (("birth_date", NepaliDateFilter),)
|
|
```
|
|
|
|
---
|
|
|
|
## 🗺️ Address Management
|
|
|
|
Manage the **Province → District → Municipality** hierarchy.
|
|
|
|
### Client-Side Chaining (Standard)
|
|
|
|
Cascading selects in the Django Admin without extra configuration.
|
|
|
|
```python
|
|
from django_nepkit import ProvinceField, DistrictField, MunicipalityField
|
|
|
|
class Address(models.Model):
|
|
province = ProvinceField()
|
|
district = DistrictField()
|
|
municipality = MunicipalityField()
|
|
```
|
|
|
|
### Server-Side Chaining (HTMX)
|
|
|
|
Enable `htmx=True` for a server-driven experience.
|
|
|
|
> [!IMPORTANT]
|
|
> **HTMX Setup:**
|
|
> Include the required URLs in your main `urls.py`:
|
|
>
|
|
> ```python
|
|
> path("nepkit/", include("django_nepkit.urls")),
|
|
> ```
|
|
|
|
---
|
|
|
|
## 🔌 API & DRF Support
|
|
|
|
Search and ordering work natively. BS year/month filtering is supported.
|
|
|
|
```python
|
|
from django_nepkit.filters import NepaliDateYearFilter
|
|
|
|
class ProfileFilter(filters.FilterSet):
|
|
# Filter by BS Year (e.g., /api/profiles/?year=2081)
|
|
year = NepaliDateYearFilter(field_name="birth_date")
|
|
```
|
|
|
|
---
|
|
|
|
## 🕒 Technical Design
|
|
|
|
This library is engineered for performance, data integrity, and local compliance.
|
|
|
|
### 1. The "Source of Truth" Strategy
|
|
We avoid on-the-fly AD-to-BS conversion during database queries because it is computationally expensive and prone to logical drift (due to lunar calendar offsets).
|
|
- **Storage**: All BS dates are stored as `VARCHAR(10)` in `YYYY-MM-DD` format.
|
|
- **Sorting**: Because `YYYY` is at the start, string-based database sorting (ascending/descending) accurately matches chronological order.
|
|
- **Indexability**: Standard B-Tree indexes work perfectly on these fields without requiring custom database functions.
|
|
- **Timezone Safety**: Dates are stored without time components, making them immune to server-side timezone shifts during saving.
|
|
|
|
### 2. Python Object Mapping
|
|
While data is stored as strings, it is automatically hydrated into rich Python objects.
|
|
- **`nepali-datetime` Integration**: Values are cast to `nepalidate` or `nepalidatetime` objects when retrieved from the database.
|
|
- **Validation**: Fields use specialized validators (e.g., `validate_nepali_phone_number`) that leverage official regional patterns.
|
|
|
|
### 3. Frontend Architecture
|
|
- **Automatic Initialization**: The library includes a lightweight JS observer that automatically initializes the datepicker for any field with the `.nepkit-datepicker` class.
|
|
- **Theme Support**: The datepicker dynamically adapts its skin based on the Django Admin's dark/light mode state.
|
|
|
|
---
|
|
|
|
## ❓ FAQ
|
|
|
|
**Q: How do I handle Null or Optional dates?**
|
|
|
|
Just like standard Django fields, pass `null=True, blank=True` to any `django-nepkit` field. The library handles empty strings and `None` values gracefully.
|
|
|
|
**Q: Can I change the database storage format?**
|
|
|
|
No. The `YYYY-MM-DD` format is hardcoded to ensure database-level sorting and indexing work consistently. However, you can change the **display** format via global settings or template filters.
|
|
|
|
**Q: How do I get Devanagari (local script) digits in my API?**
|
|
|
|
In your Serializer field or Model field, pass `ne=True`.
|
|
```python
|
|
birth_date = NepaliDateField(ne=True)
|
|
```
|
|
|
|
**Q: Is the location data up to date?**
|
|
|
|
Yes. Province, District, and Municipality data is sourced from the `nepali` Python package, which is regularly updated to reflect administrative changes in Nepal.
|
|
|
|
**Q: Does it work with standard Django Forms?**
|
|
|
|
Yes. `NepaliDateField` uses a specialized `NepaliDateFormField` that automatically handles input parsing and error reporting.
|
|
|
|
**Q: How do I migrate existing English (AD) dates to BS?**
|
|
|
|
We recommend staying on standard `DateField` for AD data. If you must convert to BS, use our [Migration Script](docs/migration_guide.py) to perform a bulk data transformation safely.
|
|
|
|
**Q: Why use VARCHAR instead of a native DateField?**
|
|
|
|
Native `DateField` in most SQL engines is locked to the Gregorian calendar. Using `VARCHAR` allows us to treat the BS date as the primary data point, avoiding the "off-by-one" conversion errors common when syncing two disparate calendars.
|
|
|
|
---
|
|
|
|
## 🤝 Community
|
|
|
|
We welcome contributions and feedback from the community.
|
|
|
|
1. **Clone**: `git clone https://github.com/S4NKALP/django-nepkit`
|
|
2. **Setup**: `uv sync`
|
|
3. **Test**: `uv run pytest`
|
|
|
|
---
|
|
|
|
## 📄 License
|
|
|
|
MIT License. Designed for the local Django ecosystem.
|