django-nepkit 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_nepkit/__init__.py +20 -0
- django_nepkit/admin.py +243 -93
- django_nepkit/conf.py +34 -0
- django_nepkit/constants.py +129 -0
- django_nepkit/filters.py +113 -0
- django_nepkit/forms.py +9 -9
- django_nepkit/lang_utils.py +52 -0
- django_nepkit/models.py +138 -161
- django_nepkit/serializers.py +127 -28
- django_nepkit/static/django_nepkit/js/address-chaining.js +129 -29
- django_nepkit/static/django_nepkit/js/nepal-data.js +1 -0
- django_nepkit/static/django_nepkit/js/nepali-datepicker-init.js +55 -46
- django_nepkit/utils.py +270 -46
- django_nepkit/validators.py +1 -1
- django_nepkit/views.py +127 -10
- django_nepkit/widgets.py +100 -31
- django_nepkit-0.2.1.dist-info/METADATA +308 -0
- django_nepkit-0.2.1.dist-info/RECORD +37 -0
- example/demo/admin.py +45 -21
- example/demo/models.py +41 -4
- example/demo/serializers.py +39 -0
- example/demo/urls.py +13 -2
- example/demo/views.py +125 -3
- example/example_project/settings.py +10 -0
- example/example_project/urls.py +1 -1
- example/manage.py +2 -2
- django_nepkit/templatetags/__init__.py +0 -0
- django_nepkit/templatetags/nepali.py +0 -74
- django_nepkit-0.1.0.dist-info/METADATA +0 -377
- django_nepkit-0.1.0.dist-info/RECORD +0 -39
- example/demo/migrations/0001_initial.py +0 -2113
- example/demo/migrations/0002_alter_person_phone_number.py +0 -18
- example/demo/migrations/0003_person_created_at_person_updated_at.py +0 -27
- example/demo/migrations/0004_alter_person_created_at_alter_person_updated_at.py +0 -23
- example/demo/migrations/0005_alter_person_created_at_alter_person_updated_at.py +0 -27
- example/demo/migrations/__init__.py +0 -0
- {django_nepkit-0.1.0.dist-info → django_nepkit-0.2.1.dist-info}/WHEEL +0 -0
- {django_nepkit-0.1.0.dist-info → django_nepkit-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {django_nepkit-0.1.0.dist-info → django_nepkit-0.2.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from rest_framework import serializers
|
|
2
|
+
from django_nepkit.serializers import (
|
|
3
|
+
NepaliDateSerializerField,
|
|
4
|
+
NepaliCurrencySerializerField,
|
|
5
|
+
NepaliLocalizedSerializerMixin,
|
|
6
|
+
)
|
|
7
|
+
from .models import Person, Citizen, AuditedPerson, Transaction
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PersonSerializer(NepaliLocalizedSerializerMixin, serializers.ModelSerializer):
|
|
11
|
+
birth_date = NepaliDateSerializerField()
|
|
12
|
+
|
|
13
|
+
class Meta:
|
|
14
|
+
model = Person
|
|
15
|
+
fields = "__all__"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TransactionSerializer(
|
|
19
|
+
NepaliLocalizedSerializerMixin, serializers.ModelSerializer
|
|
20
|
+
):
|
|
21
|
+
amount_formatted = NepaliCurrencySerializerField(source="amount")
|
|
22
|
+
|
|
23
|
+
class Meta:
|
|
24
|
+
model = Transaction
|
|
25
|
+
fields = ["id", "title", "amount", "amount_formatted", "date"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CitizenSerializer(serializers.ModelSerializer):
|
|
29
|
+
class Meta:
|
|
30
|
+
model = Citizen
|
|
31
|
+
fields = "__all__"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AuditedPersonSerializer(serializers.ModelSerializer):
|
|
35
|
+
birth_date = NepaliDateSerializerField()
|
|
36
|
+
|
|
37
|
+
class Meta:
|
|
38
|
+
model = AuditedPerson
|
|
39
|
+
fields = "__all__"
|
example/demo/urls.py
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
from django.urls import path
|
|
2
1
|
from . import views
|
|
2
|
+
from rest_framework.routers import DefaultRouter
|
|
3
|
+
from django.urls import path
|
|
3
4
|
|
|
4
5
|
app_name = "demo"
|
|
5
6
|
|
|
7
|
+
router = DefaultRouter()
|
|
8
|
+
router.register("api/persons", views.PersonViewSet, basename="person-api")
|
|
9
|
+
router.register("api/citizens", views.CitizenViewSet, basename="citizen-api")
|
|
10
|
+
router.register("api/audited", views.AuditedPersonViewSet, basename="audited-api")
|
|
11
|
+
router.register(
|
|
12
|
+
"api/transactions", views.TransactionViewSet, basename="transaction-api"
|
|
13
|
+
)
|
|
14
|
+
|
|
6
15
|
urlpatterns = [
|
|
7
16
|
path("", views.person_list, name="person-list"),
|
|
8
17
|
path("add/", views.person_create, name="person-create"),
|
|
9
|
-
|
|
18
|
+
path("transactions/add/", views.transaction_create, name="transaction-create"),
|
|
19
|
+
path("normalize/", views.address_normalize_demo, name="address-normalize"),
|
|
20
|
+
] + router.urls
|
example/demo/views.py
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
from django.shortcuts import render, redirect
|
|
2
|
-
from .models import Person
|
|
3
1
|
from django import forms
|
|
2
|
+
from django.shortcuts import render, redirect
|
|
3
|
+
from rest_framework import viewsets, filters as drf_filters
|
|
4
|
+
from django_filters import rest_framework as django_filters
|
|
5
|
+
from django_nepkit.filters import NepaliDateYearFilter, NepaliDateMonthFilter
|
|
6
|
+
from .models import Person, Citizen, AuditedPerson, Transaction
|
|
7
|
+
from .serializers import (
|
|
8
|
+
PersonSerializer,
|
|
9
|
+
CitizenSerializer,
|
|
10
|
+
AuditedPersonSerializer,
|
|
11
|
+
TransactionSerializer,
|
|
12
|
+
)
|
|
13
|
+
from django_nepkit.filters import (
|
|
14
|
+
NepaliCurrencyRangeFilter,
|
|
15
|
+
NepaliDateRangeFilter,
|
|
16
|
+
)
|
|
17
|
+
from django_nepkit.utils import normalize_address
|
|
4
18
|
|
|
5
19
|
|
|
6
20
|
class PersonForm(forms.ModelForm):
|
|
@@ -9,16 +23,25 @@ class PersonForm(forms.ModelForm):
|
|
|
9
23
|
fields = [
|
|
10
24
|
"name",
|
|
11
25
|
"birth_date",
|
|
26
|
+
"birth_date_ne",
|
|
12
27
|
"phone_number",
|
|
13
28
|
"province",
|
|
29
|
+
"province_ne",
|
|
14
30
|
"district",
|
|
31
|
+
"district_ne",
|
|
15
32
|
"municipality",
|
|
33
|
+
"municipality_ne",
|
|
16
34
|
]
|
|
17
35
|
|
|
18
36
|
|
|
19
37
|
def person_list(request):
|
|
20
38
|
persons = Person.objects.all()
|
|
21
|
-
|
|
39
|
+
transactions = Transaction.objects.all()
|
|
40
|
+
return render(
|
|
41
|
+
request,
|
|
42
|
+
"demo/person_list.html",
|
|
43
|
+
{"persons": persons, "transactions": transactions},
|
|
44
|
+
)
|
|
22
45
|
|
|
23
46
|
|
|
24
47
|
def person_create(request):
|
|
@@ -30,3 +53,102 @@ def person_create(request):
|
|
|
30
53
|
else:
|
|
31
54
|
form = PersonForm()
|
|
32
55
|
return render(request, "demo/person_form.html", {"form": form})
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TransactionForm(forms.ModelForm):
|
|
59
|
+
class Meta:
|
|
60
|
+
model = Transaction
|
|
61
|
+
fields = ["title", "amount"]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def transaction_create(request):
|
|
65
|
+
if request.method == "POST":
|
|
66
|
+
form = TransactionForm(request.POST)
|
|
67
|
+
if form.is_valid():
|
|
68
|
+
form.save()
|
|
69
|
+
return redirect("demo:person-list")
|
|
70
|
+
else:
|
|
71
|
+
form = TransactionForm()
|
|
72
|
+
return render(
|
|
73
|
+
request, "demo/person_form.html", {"form": form, "title": "Add Transaction"}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# --- API Support (DRF) ---
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class PersonViewSet(viewsets.ModelViewSet):
|
|
81
|
+
queryset = Person.objects.all()
|
|
82
|
+
serializer_class = PersonSerializer
|
|
83
|
+
|
|
84
|
+
# Sort and Search work automatically with BS date strings
|
|
85
|
+
filter_backends = [
|
|
86
|
+
django_filters.DjangoFilterBackend,
|
|
87
|
+
drf_filters.SearchFilter,
|
|
88
|
+
drf_filters.OrderingFilter,
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
ordering_fields = ["birth_date", "created_at"]
|
|
92
|
+
search_fields = ["name", "birth_date", "phone_number"]
|
|
93
|
+
|
|
94
|
+
# Simple exact date filter
|
|
95
|
+
filterset_fields = {
|
|
96
|
+
"birth_date": ["exact"],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
class PersonFilter(django_filters.FilterSet):
|
|
100
|
+
year = NepaliDateYearFilter(field_name="birth_date")
|
|
101
|
+
month = NepaliDateMonthFilter(field_name="birth_date")
|
|
102
|
+
|
|
103
|
+
class Meta:
|
|
104
|
+
model = Person
|
|
105
|
+
fields = ["province", "district"]
|
|
106
|
+
|
|
107
|
+
filterset_class = PersonFilter
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class CitizenViewSet(viewsets.ModelViewSet):
|
|
111
|
+
queryset = Citizen.objects.all()
|
|
112
|
+
serializer_class = CitizenSerializer
|
|
113
|
+
filter_backends = [drf_filters.OrderingFilter]
|
|
114
|
+
ordering_fields = ["province", "district"]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class AuditedPersonViewSet(viewsets.ModelViewSet):
|
|
118
|
+
queryset = AuditedPerson.objects.all()
|
|
119
|
+
serializer_class = AuditedPersonSerializer
|
|
120
|
+
filter_backends = [drf_filters.SearchFilter, drf_filters.OrderingFilter]
|
|
121
|
+
search_fields = ["name", "birth_date"]
|
|
122
|
+
ordering_fields = ["created_at"]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TransactionViewSet(viewsets.ModelViewSet):
|
|
126
|
+
queryset = Transaction.objects.all()
|
|
127
|
+
serializer_class = TransactionSerializer
|
|
128
|
+
filter_backends = [django_filters.DjangoFilterBackend]
|
|
129
|
+
|
|
130
|
+
class TransactionFilter(django_filters.FilterSet):
|
|
131
|
+
amount_range = NepaliCurrencyRangeFilter(field_name="amount")
|
|
132
|
+
date_range = NepaliDateRangeFilter(field_name="date")
|
|
133
|
+
|
|
134
|
+
class Meta:
|
|
135
|
+
model = Transaction
|
|
136
|
+
fields = ["title", "amount", "date"]
|
|
137
|
+
|
|
138
|
+
filterset_class = TransactionFilter
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def address_normalize_demo(request):
|
|
142
|
+
address = request.GET.get("address", "")
|
|
143
|
+
result = None
|
|
144
|
+
if address:
|
|
145
|
+
result = normalize_address(address)
|
|
146
|
+
|
|
147
|
+
if request.headers.get("HX-Request") == "true":
|
|
148
|
+
return render(
|
|
149
|
+
request, "demo/address_normalize_partial.html", {"result": result}
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
return render(
|
|
153
|
+
request, "demo/address_normalize.html", {"address": address, "result": result}
|
|
154
|
+
)
|
|
@@ -14,6 +14,8 @@ INSTALLED_APPS = [
|
|
|
14
14
|
"django.contrib.messages",
|
|
15
15
|
"django.contrib.staticfiles",
|
|
16
16
|
"django_nepkit",
|
|
17
|
+
"rest_framework",
|
|
18
|
+
"django_filters",
|
|
17
19
|
"demo",
|
|
18
20
|
]
|
|
19
21
|
|
|
@@ -73,4 +75,12 @@ TIME_ZONE = "Asia/Kathmandu"
|
|
|
73
75
|
USE_I18N = True
|
|
74
76
|
USE_TZ = True
|
|
75
77
|
|
|
78
|
+
# django-nepkit settings
|
|
79
|
+
NEPKIT = {
|
|
80
|
+
"DEFAULT_LANGUAGE": "en", # Default to Devanagari for fields and widgets
|
|
81
|
+
"DATE_INPUT_FORMATS": ["%Y-%m-%d", "%d/%m/%Y", "%d-%m-%Y"],
|
|
82
|
+
"ADMIN_DATEPICKER": True,
|
|
83
|
+
"TIME_FORMAT": 12, # 12-hour format with AM/PM
|
|
84
|
+
}
|
|
85
|
+
|
|
76
86
|
STATIC_URL = "static/"
|
example/example_project/urls.py
CHANGED
example/manage.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
|
-
"""Django
|
|
2
|
+
"""Django utility for running commands."""
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def main():
|
|
9
|
-
"""
|
|
9
|
+
"""Main entry point for Django commands."""
|
|
10
10
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
11
11
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example_project.settings")
|
|
12
12
|
try:
|
|
File without changes
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
from django import template
|
|
2
|
-
from nepali.datetime import nepalidate, nepalihumanize
|
|
3
|
-
from nepali.number import nepalinumber
|
|
4
|
-
import datetime
|
|
5
|
-
|
|
6
|
-
register = template.Library()
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def _coerce_ad_date_to_bs(value):
|
|
10
|
-
"""
|
|
11
|
-
Internal helper: if value is AD date/datetime, convert to `nepalidate`.
|
|
12
|
-
Does NOT attempt to parse strings (keeps template behavior minimal).
|
|
13
|
-
"""
|
|
14
|
-
if isinstance(value, (datetime.datetime, datetime.date)):
|
|
15
|
-
return nepalidate.from_date(value)
|
|
16
|
-
return value
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@register.filter
|
|
20
|
-
def nepali_date(value, format_str="%Y-%m-%d"):
|
|
21
|
-
"""
|
|
22
|
-
Formats a date or datetime object into a Nepali date string.
|
|
23
|
-
"""
|
|
24
|
-
if value is None:
|
|
25
|
-
return ""
|
|
26
|
-
|
|
27
|
-
value = _coerce_ad_date_to_bs(value)
|
|
28
|
-
|
|
29
|
-
if hasattr(value, "strftime"):
|
|
30
|
-
return value.strftime(format_str)
|
|
31
|
-
return value
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@register.filter
|
|
35
|
-
def nepali_date_ne(value, format_str="%Y-%m-%d"):
|
|
36
|
-
"""
|
|
37
|
-
Formats a date or datetime object into a Nepali date string (Devanagari).
|
|
38
|
-
"""
|
|
39
|
-
if value is None:
|
|
40
|
-
return ""
|
|
41
|
-
|
|
42
|
-
value = _coerce_ad_date_to_bs(value)
|
|
43
|
-
|
|
44
|
-
if hasattr(value, "strftime_ne"):
|
|
45
|
-
return value.strftime_ne(format_str)
|
|
46
|
-
return value
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@register.filter
|
|
50
|
-
def nepali_number(value):
|
|
51
|
-
"""
|
|
52
|
-
Converts a number to Devanagari.
|
|
53
|
-
"""
|
|
54
|
-
if value is None:
|
|
55
|
-
return ""
|
|
56
|
-
return nepalinumber(value).str_ne()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@register.filter
|
|
60
|
-
def nepali_humanize(value, threshold=None, format_str=None):
|
|
61
|
-
"""
|
|
62
|
-
Returns a human-readable "time ago" string in Nepali.
|
|
63
|
-
"""
|
|
64
|
-
if value is None:
|
|
65
|
-
return ""
|
|
66
|
-
|
|
67
|
-
# Threshold and format_str are optional
|
|
68
|
-
kwargs = {}
|
|
69
|
-
if threshold:
|
|
70
|
-
kwargs["threshold"] = threshold
|
|
71
|
-
if format_str:
|
|
72
|
-
kwargs["format"] = format_str
|
|
73
|
-
|
|
74
|
-
return nepalihumanize(value, **kwargs)
|