cuz-toolkit 0.1.0__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.
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: cuz-toolkit
3
+ Version: 0.1.0
4
+ Summary: A collection of Django utilities: Admin mixins, testing helpers, and common patterns
5
+ Project-URL: Homepage, https://github.com/froggen/django-toolkit
6
+ Project-URL: Repository, https://github.com/froggen/django-toolkit
7
+ Author-email: Ivan <iven12345678900@gmail.com>
8
+ License: MIT
9
+ Keywords: admin,django,mixin,permission,testing,toolkit
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Framework :: Django
13
+ Classifier: Framework :: Django :: 4.0
14
+ Classifier: Framework :: Django :: 4.1
15
+ Classifier: Framework :: Django :: 4.2
16
+ Classifier: Framework :: Django :: 5.0
17
+ Classifier: Framework :: Django :: 5.1
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Requires-Python: >=3.13
26
+ Requires-Dist: django>=4.0
27
+ Provides-Extra: unfold
28
+ Requires-Dist: django-unfold>=0.85.0; extra == 'unfold'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Django Toolkit
32
+
33
+ A collection of Django utilities: Admin mixins, testing helpers, and common patterns.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ # From GitHub
39
+ uv add git+https://github.com/froggen/django-toolkit.git
40
+
41
+ # Local development
42
+ uv add --editable ../django-toolkit
43
+ ```
44
+
45
+ ## Modules
46
+
47
+ ### toolkit.admin - Admin Mixins
48
+
49
+ ```python
50
+ from django.contrib import admin
51
+ from toolkit.admin import OwnerMixin, ReadOnlyMixin
52
+ from unfold.admin import ModelAdmin
53
+
54
+ @admin.register(Project)
55
+ class ProjectAdmin(OwnerMixin, ModelAdmin):
56
+ owner_field = "user" # Users can only edit their own projects
57
+ ```
58
+
59
+ ### toolkit.testing - Testing Utilities
60
+
61
+ ```python
62
+ from toolkit.testing import has_index_on_columns, get_table_constraints
63
+
64
+ # Verify database indexes exist
65
+ def test_status_index_exists():
66
+ assert has_index_on_columns("invoice", ["status", "created_at"])
67
+ ```
68
+
69
+ ## Available Admin Mixins
70
+
71
+ ### Permission Control
72
+
73
+ | Mixin | Description |
74
+ |-------|-------------|
75
+ | `SuperuserOnlyMixin` | Only superusers can access |
76
+ | `ReadOnlyMixin` | No add/change/delete, view only |
77
+ | `CRUDMixin` | Basic CRUD for active users |
78
+ | `OwnerMixin` | Users can only access their own data |
79
+ | `ReadOnlyOwnerMixin` | View-only for owned data |
80
+
81
+ ### Special Patterns
82
+
83
+ | Mixin | Description |
84
+ |-------|-------------|
85
+ | `ActionsOnlyMixin` | Hide save buttons, use actions only |
86
+ | `SingleObjectMixin` | Redirect to edit/add page (for one-per-user models) |
87
+
88
+ ### Inline Mixins
89
+
90
+ | Mixin | Description |
91
+ |-------|-------------|
92
+ | `InlineCRUDMixin` | CRUD for inline models |
93
+ | `ReadOnlyInlineMixin` | Read-only inline |
94
+
95
+ ### UI Helpers
96
+
97
+ | Mixin | Description |
98
+ |-------|-------------|
99
+ | `HideRelatedFieldButtonsMixin` | Hide add/edit/delete buttons on FK fields |
100
+
101
+ ## Testing Utilities
102
+
103
+ | Function | Description |
104
+ |----------|-------------|
105
+ | `get_table_constraints(table_name)` | Get all constraints and indexes for a table |
106
+ | `has_index_on_columns(table_name, columns)` | Check if an index exists on specified columns |
107
+
108
+ ## Usage Examples
109
+
110
+ ### Owner-based Permission
111
+
112
+ ```python
113
+ @admin.register(Article)
114
+ class ArticleAdmin(OwnerMixin, ModelAdmin):
115
+ owner_field = "author"
116
+ list_display = ["title", "author", "created_at"]
117
+ ```
118
+
119
+ ### Nested Owner Field
120
+
121
+ ```python
122
+ @admin.register(Comment)
123
+ class CommentAdmin(OwnerMixin, ModelAdmin):
124
+ owner_field = "post__author" # Comment -> Post -> Author
125
+ ```
126
+
127
+ ### Read-only with Owner Filter
128
+
129
+ ```python
130
+ @admin.register(Order)
131
+ class OrderAdmin(ReadOnlyOwnerMixin, ModelAdmin):
132
+ owner_field = "customer"
133
+ ```
134
+
135
+ ### Single Object (e.g., User Profile)
136
+
137
+ ```python
138
+ @admin.register(UserProfile)
139
+ class UserProfileAdmin(SingleObjectMixin, OwnerMixin, ModelAdmin):
140
+ owner_field = "user"
141
+ ```
142
+
143
+ ### Actions Only (e.g., Approval Workflow)
144
+
145
+ ```python
146
+ @admin.register(WithdrawalRequest)
147
+ class WithdrawalRequestAdmin(ActionsOnlyMixin, ModelAdmin):
148
+ readonly_fields = ["amount", "status", "created_at"]
149
+ actions_submit_line = ["approve_action", "reject_action"]
150
+ ```
151
+
152
+ ### Index Validation in Tests
153
+
154
+ ```python
155
+ import pytest
156
+ from toolkit.testing import has_index_on_columns
157
+
158
+ @pytest.mark.django_db
159
+ class TestDatabaseIndexes:
160
+ def test_composite_index_exists(self):
161
+ assert has_index_on_columns("booking", ["status", "start"])
162
+
163
+ def test_single_column_index_exists(self):
164
+ assert has_index_on_columns("payment", ["transaction_id"])
165
+ ```
166
+
167
+ ## License
168
+
169
+ MIT
@@ -0,0 +1,35 @@
1
+ toolkit/__init__.py,sha256=o-0gvX7PpNFBRoYunG6NjRmDMLvkI52SsWm5KHHkr08,488
2
+ toolkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ toolkit/pytest_plugin.py,sha256=0r8p_-7dDakPBrtAuAeP4j0F7j4S2-I--DYV9OjHvOw,4555
4
+ toolkit/admin/__init__.py,sha256=eVqZ4v2NUZzK9AHfHk5zi9gu77O2orSGOZLKLYSikjM,923
5
+ toolkit/admin/mixins.py,sha256=1cDV2Hyz4kMvTRu2amem3N2h-hCFcMkqm7eTv7gSZfo,19483
6
+ toolkit/ecpay/__init__.py,sha256=JBCxHh91_yWO5doh_ziNqDvH4EyEiWIDuVRTwi1ZkXI,1545
7
+ toolkit/ecpay/client.py,sha256=i8gPeruSoMm77WxXUdkYNZqpqzNr_PQdt2S3B9nzgKA,5738
8
+ toolkit/ecpay/constants.py,sha256=4avwiS1ZO9EE5X9oj-iGOjbDqY7rzDC8SN3XbC_xP8M,3059
9
+ toolkit/testing/__init__.py,sha256=Ec6mU7QQpMJraW9PZHZ_VP2tjsIZE26CmwQ-dS9DABA,458
10
+ toolkit/testing/db.py,sha256=jbRHf0EdqWBaxJDqvkZd3dSoDoreIbPR04L7eCbNXXw,2241
11
+ toolkit/tw_address/__init__.py,sha256=w1o8KpI_qBxtbE6qBN0uJuYWSKaTpmXI_I3EFSWjNMw,1117
12
+ toolkit/tw_address/apps.py,sha256=mwjoantAX535pMh_v-eXCxapZYta0IXK5RClD1CoaFk,555
13
+ toolkit/tw_address/static/toolkit/js/tw-city-admin.js,sha256=zcTI4PJyn4qKXURd1LBIK3LHCwa9yOnrra_wYot9wVA,18060
14
+ toolkit/tw_address/static/toolkit/js/tw-city-selector.min.js,sha256=hZYD69DCuACzSTM46JaQmmUGaGACVGasofM9IWItwdo,27129
15
+ toolkit/tw_banks/__init__.py,sha256=dHbpAFtNLaPk12c1DJYh8eNqibLJhvUiTiMCkfVX-5U,1902
16
+ toolkit/tw_banks/data.json,sha256=hZBSgVxMs-xuuXk6gc84KUg87cjHoNFEvMErPpt0jL4,5034
17
+ toolkit/unfold/__init__.py,sha256=k96xa2MR4umsmKCsWA87t3-f9kKUFDjL7CeZuxeAnNk,423
18
+ toolkit/unfold/apps.py,sha256=xAqdMP-Dk0Xo_mbnWqpihW3lDzoiqZBTgP6h6C-CA8w,1719
19
+ toolkit/unfold/conf.py,sha256=aObQH8x3MsEXqCnevCWfVZ-MneOaVKBTj-wRNNpk0pw,1811
20
+ toolkit/unfold/urls.py,sha256=XRKgWIH_Ux_MhDjoLozP11wuZfUPttk0lMK14L-32PA,305
21
+ toolkit/unfold/views.py,sha256=Arq4xA5xyXMz_bPtsnLTAchfcYUQHx88VtW4iwBWa2A,1462
22
+ toolkit/unfold/widgets.py,sha256=qQc1nAVSJQHZI4fZ2bimh66P4kamKcE3-rRsmJTYaN0,466
23
+ toolkit/unfold/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=rTwLXMlyGC92KeGBbTIpN15WJehSfnqJ38LcKQTdHSk,1033
24
+ toolkit/unfold/locale/zh_Hant/LC_MESSAGES/django.po,sha256=wkJ03idAzUGjrO1lfrc6zzj-nC-uBfSTeSuV1KWv-sk,2191
25
+ toolkit/unfold/locale_unfold/zh_Hant/LC_MESSAGES/django.mo,sha256=weXhzpnPlA4P5IFPHY7C-8Rm4yJaEP7u0FOvX0LJdTA,13309
26
+ toolkit/unfold/locale_unfold/zh_Hant/LC_MESSAGES/django.po,sha256=0NUGfGeG6Y-V6Xknm-wF21stwbNEGLuV2uZkL-GaRHE,33157
27
+ toolkit/unfold/static/toolkit/unfold/css/trix.css,sha256=HF78kjrIwTDHfd6RJN70_J5XaY79g4WklkbZ0GQqJ8w,105
28
+ toolkit/unfold/static/toolkit/unfold/js/trix-upload.js,sha256=Vu3o0CD295Gz2Q84eNatNX3LQypEJjPl1gP1iqlo910,2239
29
+ toolkit/unfold/templates/unfold/forms/helpers/toolbar.html,sha256=yN5DcidbsKnHL7q-stUxkGY8QCBANlPntHWGH78b5xM,10897
30
+ toolkit/utils/__init__.py,sha256=4O7REA-iPEYrCKyY7wmTib7Jxoyw8k_Wm9_CbjIzEZU,120
31
+ toolkit/utils/upload.py,sha256=8pzQuh_CATgNUM-KFRcTBGnB0yfOaH8pK9VQgba184g,2025
32
+ cuz_toolkit-0.1.0.dist-info/METADATA,sha256=vxwWi6_0YIzM6t-N1M2E3r1-DBt33Ggyu6nvDLrVf5c,4607
33
+ cuz_toolkit-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
34
+ cuz_toolkit-0.1.0.dist-info/entry_points.txt,sha256=kqLGjnbYkJ0MtFMU3EhbZY7eULRzhDsShaeqb6lYuGU,47
35
+ cuz_toolkit-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [pytest11]
2
+ cuz_toolkit = toolkit.pytest_plugin
toolkit/__init__.py ADDED
@@ -0,0 +1,12 @@
1
+ """
2
+ Django Toolkit - A collection of Django utilities for common development patterns.
3
+
4
+ Modules:
5
+ toolkit.admin - Admin mixins for permission control
6
+ toolkit.ecpay - ECPay payment gateway integration (signing, verification, constants)
7
+ toolkit.testing - Testing utilities for database validation
8
+ toolkit.unfold - Unfold Admin extension (Trix editor image upload)
9
+ toolkit.utils - Common utilities (UploadToUniquePath, etc.)
10
+ """
11
+
12
+ __version__ = "0.1.0" # pragma: no cover
@@ -0,0 +1,42 @@
1
+ """
2
+ Django Admin Mixins - A collection of Django Admin mixins for permission control.
3
+
4
+ Usage:
5
+ from toolkit.admin import OwnerMixin, ReadOnlyMixin, CRUDMixin
6
+
7
+ @admin.register(MyModel)
8
+ class MyModelAdmin(OwnerMixin, ModelAdmin):
9
+ owner_field = "user"
10
+ """
11
+
12
+ from toolkit.admin.mixins import (
13
+ ActionsOnlyMixin,
14
+ CRUDMixin,
15
+ EditOnlyInlineMixin,
16
+ EditOnlyMixin,
17
+ HideRelatedFieldButtonsMixin,
18
+ InlineCRUDMixin,
19
+ OwnerMixin,
20
+ ReadOnlyInlineMixin,
21
+ ReadOnlyMixin,
22
+ ReadOnlyOwnerMixin,
23
+ SelfOnlyMixin,
24
+ SingleObjectMixin,
25
+ SuperuserOnlyMixin,
26
+ )
27
+
28
+ __all__ = [
29
+ "ActionsOnlyMixin",
30
+ "CRUDMixin",
31
+ "EditOnlyInlineMixin",
32
+ "EditOnlyMixin",
33
+ "HideRelatedFieldButtonsMixin",
34
+ "InlineCRUDMixin",
35
+ "OwnerMixin",
36
+ "ReadOnlyInlineMixin",
37
+ "ReadOnlyMixin",
38
+ "ReadOnlyOwnerMixin",
39
+ "SelfOnlyMixin",
40
+ "SingleObjectMixin",
41
+ "SuperuserOnlyMixin",
42
+ ]