PyInventory 0.21.3__tar.gz → 0.22.0__tar.gz
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.
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.gitignore +2 -3
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.pre-commit-config.yaml +1 -1
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.run/Template Django tests.run.xml +1 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.run/manage.py --help.run.xml +2 -2
- pyinventory-0.22.0/.run/manage.py make_messages.run.xml +25 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.run/manage.py update_req.run.xml +2 -2
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.run/unittests ___all___.run.xml +1 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/PKG-INFO +10 -4
- {pyinventory-0.21.3 → pyinventory-0.22.0}/README.md +9 -3
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/__init__.py +2 -2
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/item.py +11 -14
- pyinventory-0.22.0/inventory/locale/ca/LC_MESSAGES/django.mo +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/locale/ca/LC_MESSAGES/django.po +19 -1
- pyinventory-0.22.0/inventory/locale/de/LC_MESSAGES/django.mo +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/locale/de/LC_MESSAGES/django.po +21 -3
- pyinventory-0.22.0/inventory/locale/en/LC_MESSAGES/django.mo +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/locale/en/LC_MESSAGES/django.po +21 -3
- pyinventory-0.22.0/inventory/locale/es/LC_MESSAGES/django.mo +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/locale/es/LC_MESSAGES/django.po +19 -1
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/management/commands/seed_data.py +20 -3
- pyinventory-0.22.0/inventory/migrations/0015_itemmaincategory_itemmodel_category.py +32 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/item.py +33 -0
- pyinventory-0.22.0/inventory/persistent_filters.py +47 -0
- pyinventory-0.22.0/inventory/tests/test_management_command_seed_data.py +69 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/settings/local.py +0 -3
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_item.py +87 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_item_auto_group_items_1.snapshot.html +10 -2
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_item_normal_user_create_minimal_item_1.snapshot.html +30 -10
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_item_normal_user_create_minimal_item_2.snapshot.html +30 -10
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_superuser_admin_index_1.snapshot.html +17 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_inventory_commands_help_1.snapshot.txt +3 -3
- {pyinventory-0.21.3 → pyinventory-0.22.0}/pyproject.toml +5 -4
- pyinventory-0.22.0/uv.lock +2240 -0
- pyinventory-0.21.3/inventory/locale/ca/LC_MESSAGES/django.mo +0 -0
- pyinventory-0.21.3/inventory/locale/de/LC_MESSAGES/django.mo +0 -0
- pyinventory-0.21.3/inventory/locale/en/LC_MESSAGES/django.mo +0 -0
- pyinventory-0.21.3/inventory/locale/es/LC_MESSAGES/django.mo +0 -0
- pyinventory-0.21.3/inventory/tests/test_management_command_seed_data.py +0 -49
- pyinventory-0.21.3/uv.lock +0 -2124
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.editorconfig +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.github/workflows/tests.yml +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.idea/.gitignore +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.pre-commit-hooks.yaml +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/.run/Template Python.run.xml +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/AUTHORS +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/LICENSE +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/dist/.gitignore +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/base.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/location.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/memo.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/admin/tagulous_fix.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/apps.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/checks.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/ckeditor_upload.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/constants.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/context_processors.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/forms.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/management/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/management/commands/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/management/commands/tree.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/middlewares.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0001_initial.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0002_auto_20201017_2211.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0003_auto_20201024_1830.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0004_item_user_images.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0005_serve_uploads_by_django_tools.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0006_refactor_image_model.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0007_add_file_attachment.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0008_last_check_datetime.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0009_add_memo.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0010_version_protect_models.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0011_parent_tree1.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0012_parent_tree2.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0013_alter_itemmodel_location.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/0014_alter_itemmodel_description_and_more.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/migrations/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/base.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/links.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/location.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/models/memo.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/parent_tree.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/permissions.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/request_dict.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/signals.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/string_utils.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/templates/admin/item/related_items.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/templates/admin/location/items.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/fixtures/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/fixtures/users.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_admin_location.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_admin_location_empty_change_list_1.snapshot.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_item_images.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_link_model.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_management_command_tree.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_parent_tree.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory/tests/test_parent_tree_model.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/__main__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/middlewares.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/settings/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/settings/prod.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/settings/tests.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/templates/admin/base_site.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/templates/admin/login.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/__init__.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/fixtures.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/mocks.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/playwright_utils.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_item_login_1.snapshot.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_memo.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_admin_memo_normal_user_create_minimal_item_1.snapshot.html +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_inventory_commands.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_migrations.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_models_item.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_playwright_admin.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_project_setup.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/tests/test_readme_history.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/urls.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/inventory_project/wsgi.py +0 -0
- {pyinventory-0.21.3 → pyinventory-0.22.0}/manage.py +0 -0
|
@@ -9,7 +9,6 @@ __pycache__
|
|
|
9
9
|
!.github
|
|
10
10
|
!.run
|
|
11
11
|
!.editorconfig
|
|
12
|
-
!.flake8
|
|
13
12
|
!.gitignore
|
|
14
13
|
!.pre-commit-config.yaml
|
|
15
14
|
!.pre-commit-hooks.yaml
|
|
@@ -20,8 +19,8 @@ __pycache__
|
|
|
20
19
|
!/backups/.gitkeep
|
|
21
20
|
|
|
22
21
|
# from test projects:
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/static/
|
|
23
|
+
/media/
|
|
25
24
|
*.sqlite3
|
|
26
25
|
*.json
|
|
27
26
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<option name="PARENT_ENVS" value="true" />
|
|
7
7
|
<envs>
|
|
8
8
|
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
|
+
<env name="RAISE_SNAPSHOT_ERRORS" value="0" />
|
|
9
10
|
<env name="DJANGO_SETTINGS_MODULE" value="inventory_project.settings.tests" />
|
|
10
11
|
</envs>
|
|
11
12
|
<option name="SDK_HOME" value="" />
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
<option name="SDK_HOME" value="" />
|
|
11
11
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
|
12
12
|
<option name="IS_MODULE_SDK" value="true" />
|
|
13
|
-
<option name="ADD_CONTENT_ROOTS" value="
|
|
14
|
-
<option name="ADD_SOURCE_ROOTS" value="
|
|
13
|
+
<option name="ADD_CONTENT_ROOTS" value="false" />
|
|
14
|
+
<option name="ADD_SOURCE_ROOTS" value="false" />
|
|
15
15
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
|
16
16
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/manage.py" />
|
|
17
17
|
<option name="PARAMETERS" value="--help" />
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="manage.py make_messages" type="PythonConfigurationType" factoryName="Python">
|
|
3
|
+
<module name="PyInventory" />
|
|
4
|
+
<option name="ENV_FILES" value="" />
|
|
5
|
+
<option name="INTERPRETER_OPTIONS" value="" />
|
|
6
|
+
<option name="PARENT_ENVS" value="true" />
|
|
7
|
+
<envs>
|
|
8
|
+
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
|
+
</envs>
|
|
10
|
+
<option name="SDK_HOME" value="" />
|
|
11
|
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
|
12
|
+
<option name="IS_MODULE_SDK" value="true" />
|
|
13
|
+
<option name="ADD_CONTENT_ROOTS" value="false" />
|
|
14
|
+
<option name="ADD_SOURCE_ROOTS" value="false" />
|
|
15
|
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
|
16
|
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/manage.py" />
|
|
17
|
+
<option name="PARAMETERS" value="make_messages" />
|
|
18
|
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
19
|
+
<option name="EMULATE_TERMINAL" value="true" />
|
|
20
|
+
<option name="MODULE_MODE" value="false" />
|
|
21
|
+
<option name="REDIRECT_INPUT" value="false" />
|
|
22
|
+
<option name="INPUT_FILE" value="" />
|
|
23
|
+
<method v="2" />
|
|
24
|
+
</configuration>
|
|
25
|
+
</component>
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
<option name="SDK_HOME" value="" />
|
|
11
11
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
|
12
12
|
<option name="IS_MODULE_SDK" value="true" />
|
|
13
|
-
<option name="ADD_CONTENT_ROOTS" value="
|
|
14
|
-
<option name="ADD_SOURCE_ROOTS" value="
|
|
13
|
+
<option name="ADD_CONTENT_ROOTS" value="false" />
|
|
14
|
+
<option name="ADD_SOURCE_ROOTS" value="false" />
|
|
15
15
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
|
16
16
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/manage.py" />
|
|
17
17
|
<option name="PARAMETERS" value="update_req" />
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<option name="PARENT_ENVS" value="true" />
|
|
7
7
|
<envs>
|
|
8
8
|
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
|
+
<env name="RAISE_SNAPSHOT_ERRORS" value="0" />
|
|
9
10
|
<env name="DJANGO_SETTINGS_MODULE" value="inventory_project.settings.tests" />
|
|
10
11
|
</envs>
|
|
11
12
|
<option name="SDK_HOME" value="" />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyInventory
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: Web based management to catalog things including state and location etc. using Python/Django.
|
|
5
5
|
Project-URL: Documentation, https://github.com/jedie/PyInventory
|
|
6
6
|
Project-URL: Source, https://github.com/jedie/PyInventory
|
|
@@ -196,6 +196,12 @@ To make a new release, do this:
|
|
|
196
196
|
|
|
197
197
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
198
198
|
|
|
199
|
+
* [v0.22.0](https://github.com/jedie/PyInventory/compare/v0.21.4...v0.22.0)
|
|
200
|
+
* 2025-10-16 - Add tests for PersistentRelatedFieldListFilter
|
|
201
|
+
* 2025-09-21 - NEW: Add a persistent "Main Category"
|
|
202
|
+
* 2025-09-21 - fix for django-admin-sortable2/issues/363
|
|
203
|
+
* [v0.21.4](https://github.com/jedie/PyInventory/compare/v0.21.3...v0.21.4)
|
|
204
|
+
* 2025-09-21 - Because of PyPi download errors: release as v0.21.4
|
|
199
205
|
* [v0.21.3](https://github.com/jedie/PyInventory/compare/v0.21.2...v0.21.3)
|
|
200
206
|
* 2025-09-21 - Enhance change list filters by using RelatedOnlyFieldListFilter
|
|
201
207
|
* 2025-09-21 - Update requirements
|
|
@@ -211,15 +217,15 @@ To make a new release, do this:
|
|
|
211
217
|
* [v0.21.2](https://github.com/jedie/PyInventory/compare/v0.21.1...v0.21.2)
|
|
212
218
|
* 2025-09-09 - Update project, e.g.: Darker -> Ruff and fix tests
|
|
213
219
|
* 2025-05-01 - Fix local dev server: Don't enforce https
|
|
220
|
+
|
|
221
|
+
<details><summary>Expand older history entries ...</summary>
|
|
222
|
+
|
|
214
223
|
* [v0.21.1](https://github.com/jedie/PyInventory/compare/v0.21.0...v0.21.1)
|
|
215
224
|
* 2025-05-01 - Replace setuptools with hatchling
|
|
216
225
|
* 2025-04-30 - Update requirements and some small code parts
|
|
217
226
|
* [v0.21.0](https://github.com/jedie/PyInventory/compare/v0.20.1...v0.21.0)
|
|
218
227
|
* 2025-03-23 - Bugfix publish: setuptools missing
|
|
219
228
|
* 2025-03-23 - Migrate "pip-tools" -> "uv" and remove tox
|
|
220
|
-
|
|
221
|
-
<details><summary>Expand older history entries ...</summary>
|
|
222
|
-
|
|
223
229
|
* [v0.20.1](https://github.com/jedie/PyInventory/compare/v0.20.0...v0.20.1)
|
|
224
230
|
* 2024-09-05 - switched to https://github.com/jazzband/django-tinymce/
|
|
225
231
|
* [v0.20.0](https://github.com/jedie/PyInventory/compare/v0.19.3...v0.20.0)
|
|
@@ -166,6 +166,12 @@ To make a new release, do this:
|
|
|
166
166
|
|
|
167
167
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
168
168
|
|
|
169
|
+
* [v0.22.0](https://github.com/jedie/PyInventory/compare/v0.21.4...v0.22.0)
|
|
170
|
+
* 2025-10-16 - Add tests for PersistentRelatedFieldListFilter
|
|
171
|
+
* 2025-09-21 - NEW: Add a persistent "Main Category"
|
|
172
|
+
* 2025-09-21 - fix for django-admin-sortable2/issues/363
|
|
173
|
+
* [v0.21.4](https://github.com/jedie/PyInventory/compare/v0.21.3...v0.21.4)
|
|
174
|
+
* 2025-09-21 - Because of PyPi download errors: release as v0.21.4
|
|
169
175
|
* [v0.21.3](https://github.com/jedie/PyInventory/compare/v0.21.2...v0.21.3)
|
|
170
176
|
* 2025-09-21 - Enhance change list filters by using RelatedOnlyFieldListFilter
|
|
171
177
|
* 2025-09-21 - Update requirements
|
|
@@ -181,15 +187,15 @@ To make a new release, do this:
|
|
|
181
187
|
* [v0.21.2](https://github.com/jedie/PyInventory/compare/v0.21.1...v0.21.2)
|
|
182
188
|
* 2025-09-09 - Update project, e.g.: Darker -> Ruff and fix tests
|
|
183
189
|
* 2025-05-01 - Fix local dev server: Don't enforce https
|
|
190
|
+
|
|
191
|
+
<details><summary>Expand older history entries ...</summary>
|
|
192
|
+
|
|
184
193
|
* [v0.21.1](https://github.com/jedie/PyInventory/compare/v0.21.0...v0.21.1)
|
|
185
194
|
* 2025-05-01 - Replace setuptools with hatchling
|
|
186
195
|
* 2025-04-30 - Update requirements and some small code parts
|
|
187
196
|
* [v0.21.0](https://github.com/jedie/PyInventory/compare/v0.20.1...v0.21.0)
|
|
188
197
|
* 2025-03-23 - Bugfix publish: setuptools missing
|
|
189
198
|
* 2025-03-23 - Migrate "pip-tools" -> "uv" and remove tox
|
|
190
|
-
|
|
191
|
-
<details><summary>Expand older history entries ...</summary>
|
|
192
|
-
|
|
193
199
|
* [v0.20.1](https://github.com/jedie/PyInventory/compare/v0.20.0...v0.20.1)
|
|
194
200
|
* 2024-09-05 - switched to https://github.com/jazzband/django-tinymce/
|
|
195
201
|
* [v0.20.0](https://github.com/jedie/PyInventory/compare/v0.19.3...v0.20.0)
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Web based management to catalog things including state and location etc. using Python/Django.
|
|
4
4
|
|
|
5
5
|
created 14.20.2020 by Jens Diemer <opensource@jensdiemer.de>
|
|
6
|
-
:copyleft: 2020-
|
|
6
|
+
:copyleft: 2020-2025 by the PyInventory team, see AUTHORS for more details.
|
|
7
7
|
:license: GNU GPL v3 or above, see LICENSE for more details.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# See https://packaging.python.org/en/latest/specifications/version-specifiers/
|
|
11
|
-
__version__ = '0.
|
|
11
|
+
__version__ = '0.22.0'
|
|
12
12
|
__author__ = 'Jens Diemer <PyInventory@jensdiemer.de>'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
import tagulous
|
|
4
|
-
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
|
|
4
|
+
from adminsortable2.admin import SortableAdminBase, SortableAdminMixin, SortableInlineAdminMixin
|
|
5
5
|
from django.conf import settings
|
|
6
6
|
from django.contrib import admin
|
|
7
7
|
from django.template.loader import render_to_string
|
|
@@ -20,13 +20,19 @@ from inventory.admin.base import (
|
|
|
20
20
|
)
|
|
21
21
|
from inventory.admin.tagulous_fix import TagulousModelAdminFix
|
|
22
22
|
from inventory.models import ItemLinkModel, ItemModel
|
|
23
|
-
from inventory.models.item import ItemFileModel, ItemImageModel
|
|
23
|
+
from inventory.models.item import ItemFileModel, ItemImageModel, ItemMainCategory
|
|
24
|
+
from inventory.persistent_filters import PersistentRelatedFieldListFilter
|
|
24
25
|
from inventory.string_utils import ltruncatechars
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
logger = logging.getLogger(__name__)
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
@admin.register(ItemMainCategory)
|
|
32
|
+
class ItemMainCategoryAdmin(SortableAdminMixin, admin.ModelAdmin):
|
|
33
|
+
list_display = ('order', 'name')
|
|
34
|
+
|
|
35
|
+
|
|
30
36
|
class ItemLinkModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.TabularInline):
|
|
31
37
|
model = ItemLinkModel
|
|
32
38
|
extra = 0
|
|
@@ -46,7 +52,7 @@ class ItemModelResource(ModelResource):
|
|
|
46
52
|
|
|
47
53
|
|
|
48
54
|
@admin.register(ItemModel)
|
|
49
|
-
class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin,
|
|
55
|
+
class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminBase, BaseUserAdmin):
|
|
50
56
|
@admin.display(description=_('Related items'))
|
|
51
57
|
def related_items(self, obj):
|
|
52
58
|
if obj.pk is None:
|
|
@@ -95,6 +101,7 @@ class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminMixi
|
|
|
95
101
|
ordering = ('path_str',)
|
|
96
102
|
list_display_links = ()
|
|
97
103
|
list_filter = (
|
|
104
|
+
('category', PersistentRelatedFieldListFilter),
|
|
98
105
|
LimitTreeDepthListFilter,
|
|
99
106
|
('kind', admin.RelatedOnlyFieldListFilter),
|
|
100
107
|
('location', admin.RelatedOnlyFieldListFilter),
|
|
@@ -118,7 +125,7 @@ class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminMixi
|
|
|
118
125
|
_('Basic'),
|
|
119
126
|
{
|
|
120
127
|
'fields': (
|
|
121
|
-
'kind',
|
|
128
|
+
('category', 'kind'),
|
|
122
129
|
('producer', 'name'),
|
|
123
130
|
'description',
|
|
124
131
|
'tags',
|
|
@@ -161,15 +168,5 @@ class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminMixi
|
|
|
161
168
|
readonly_fields = ('id', 'create_dt', 'update_dt', 'user', 'related_items')
|
|
162
169
|
inlines = (ItemImageModelInline, ItemFileModelInline, ItemLinkModelInline)
|
|
163
170
|
|
|
164
|
-
def get_list_display(self, request):
|
|
165
|
-
list_display = list(super().get_list_display(request))
|
|
166
|
-
|
|
167
|
-
# FIXME: SortableAdminMixin.get_list_display() adds this, we didn't need here:
|
|
168
|
-
# See: https://github.com/jrief/django-admin-sortable2/issues/363
|
|
169
|
-
if '_reorder_' in list_display:
|
|
170
|
-
list_display.remove('_reorder_')
|
|
171
|
-
|
|
172
|
-
return list_display
|
|
173
|
-
|
|
174
171
|
|
|
175
172
|
tagulous.admin.enhance(ItemModel, ItemModelAdmin)
|
|
Binary file
|
|
@@ -7,7 +7,7 @@ msgid ""
|
|
|
7
7
|
msgstr ""
|
|
8
8
|
"Project-Id-Version: \n"
|
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
10
|
+
"POT-Creation-Date: 2025-10-16 10:51+0200\n"
|
|
11
11
|
"PO-Revision-Date: 2022-09-30 20:07+0200\n"
|
|
12
12
|
"Last-Translator: Jaume López\n"
|
|
13
13
|
"Language-Team: \n"
|
|
@@ -102,6 +102,24 @@ msgstr "Nom"
|
|
|
102
102
|
msgid "BaseItemAttachmentModel.name.help_text"
|
|
103
103
|
msgstr ""
|
|
104
104
|
|
|
105
|
+
msgid "ItemMainCategory.name.verbose_name"
|
|
106
|
+
msgstr ""
|
|
107
|
+
|
|
108
|
+
msgid "ItemMainCategory.name.help_text"
|
|
109
|
+
msgstr " "
|
|
110
|
+
|
|
111
|
+
msgid "ItemMainCategory.verbose_name"
|
|
112
|
+
msgstr ""
|
|
113
|
+
|
|
114
|
+
msgid "ItemMainCategory.verbose_name_plural"
|
|
115
|
+
msgstr ""
|
|
116
|
+
|
|
117
|
+
msgid "ItemModel.category.verbose_name"
|
|
118
|
+
msgstr ""
|
|
119
|
+
|
|
120
|
+
msgid "ItemModel.category.help_text"
|
|
121
|
+
msgstr " "
|
|
122
|
+
|
|
105
123
|
msgid "ItemModel.kind.verbose_name"
|
|
106
124
|
msgstr "Tipus"
|
|
107
125
|
|
|
Binary file
|
|
@@ -7,8 +7,8 @@ msgid ""
|
|
|
7
7
|
msgstr ""
|
|
8
8
|
"Project-Id-Version: \n"
|
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
11
|
-
"PO-Revision-Date:
|
|
10
|
+
"POT-Creation-Date: 2025-10-16 10:51+0200\n"
|
|
11
|
+
"PO-Revision-Date: 2025-09-21 17:34+0200\n"
|
|
12
12
|
"Last-Translator: Jens Diemer\n"
|
|
13
13
|
"Language-Team: \n"
|
|
14
14
|
"Language: de\n"
|
|
@@ -16,7 +16,7 @@ msgstr ""
|
|
|
16
16
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
17
|
"Content-Transfer-Encoding: 8bit\n"
|
|
18
18
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
19
|
-
"X-Generator: Poedit 2
|
|
19
|
+
"X-Generator: Poedit 3.4.2\n"
|
|
20
20
|
|
|
21
21
|
msgid "Limit tree depth"
|
|
22
22
|
msgstr "Tiefe des Baumes"
|
|
@@ -101,6 +101,24 @@ msgstr "Name"
|
|
|
101
101
|
msgid "BaseItemAttachmentModel.name.help_text"
|
|
102
102
|
msgstr "Optionalen Namen (Wird automatisch aus dem Dateinamen gesetzt)"
|
|
103
103
|
|
|
104
|
+
msgid "ItemMainCategory.name.verbose_name"
|
|
105
|
+
msgstr "Kategorie"
|
|
106
|
+
|
|
107
|
+
msgid "ItemMainCategory.name.help_text"
|
|
108
|
+
msgstr " "
|
|
109
|
+
|
|
110
|
+
msgid "ItemMainCategory.verbose_name"
|
|
111
|
+
msgstr "Kategorie"
|
|
112
|
+
|
|
113
|
+
msgid "ItemMainCategory.verbose_name_plural"
|
|
114
|
+
msgstr "Kategorien"
|
|
115
|
+
|
|
116
|
+
msgid "ItemModel.category.verbose_name"
|
|
117
|
+
msgstr "Kategorie"
|
|
118
|
+
|
|
119
|
+
msgid "ItemModel.category.help_text"
|
|
120
|
+
msgstr " "
|
|
121
|
+
|
|
104
122
|
msgid "ItemModel.kind.verbose_name"
|
|
105
123
|
msgstr "Art"
|
|
106
124
|
|
|
Binary file
|
|
@@ -7,8 +7,8 @@ msgid ""
|
|
|
7
7
|
msgstr ""
|
|
8
8
|
"Project-Id-Version: \n"
|
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
11
|
-
"PO-Revision-Date:
|
|
10
|
+
"POT-Creation-Date: 2025-10-16 10:51+0200\n"
|
|
11
|
+
"PO-Revision-Date: 2025-09-21 17:36+0200\n"
|
|
12
12
|
"Last-Translator: Jens Diemer\n"
|
|
13
13
|
"Language-Team: \n"
|
|
14
14
|
"Language: en\n"
|
|
@@ -16,7 +16,7 @@ msgstr ""
|
|
|
16
16
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
17
|
"Content-Transfer-Encoding: 8bit\n"
|
|
18
18
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
19
|
-
"X-Generator: Poedit 2
|
|
19
|
+
"X-Generator: Poedit 3.4.2\n"
|
|
20
20
|
|
|
21
21
|
msgid "Limit tree depth"
|
|
22
22
|
msgstr ""
|
|
@@ -101,6 +101,24 @@ msgstr "Name"
|
|
|
101
101
|
msgid "BaseItemAttachmentModel.name.help_text"
|
|
102
102
|
msgstr ""
|
|
103
103
|
|
|
104
|
+
msgid "ItemMainCategory.name.verbose_name"
|
|
105
|
+
msgstr "Name"
|
|
106
|
+
|
|
107
|
+
msgid "ItemMainCategory.name.help_text"
|
|
108
|
+
msgstr " "
|
|
109
|
+
|
|
110
|
+
msgid "ItemMainCategory.verbose_name"
|
|
111
|
+
msgstr "Category"
|
|
112
|
+
|
|
113
|
+
msgid "ItemMainCategory.verbose_name_plural"
|
|
114
|
+
msgstr "Categories"
|
|
115
|
+
|
|
116
|
+
msgid "ItemModel.category.verbose_name"
|
|
117
|
+
msgstr "Category"
|
|
118
|
+
|
|
119
|
+
msgid "ItemModel.category.help_text"
|
|
120
|
+
msgstr " "
|
|
121
|
+
|
|
104
122
|
msgid "ItemModel.kind.verbose_name"
|
|
105
123
|
msgstr "Kind"
|
|
106
124
|
|
|
Binary file
|
|
@@ -7,7 +7,7 @@ msgid ""
|
|
|
7
7
|
msgstr ""
|
|
8
8
|
"Project-Id-Version: \n"
|
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
10
|
+
"POT-Creation-Date: 2025-10-16 10:51+0200\n"
|
|
11
11
|
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
|
|
12
12
|
"Last-Translator: Jaume López\n"
|
|
13
13
|
"Language-Team: \n"
|
|
@@ -102,6 +102,24 @@ msgstr "Nombre"
|
|
|
102
102
|
msgid "BaseItemAttachmentModel.name.help_text"
|
|
103
103
|
msgstr ""
|
|
104
104
|
|
|
105
|
+
msgid "ItemMainCategory.name.verbose_name"
|
|
106
|
+
msgstr ""
|
|
107
|
+
|
|
108
|
+
msgid "ItemMainCategory.name.help_text"
|
|
109
|
+
msgstr " "
|
|
110
|
+
|
|
111
|
+
msgid "ItemMainCategory.verbose_name"
|
|
112
|
+
msgstr ""
|
|
113
|
+
|
|
114
|
+
msgid "ItemMainCategory.verbose_name_plural"
|
|
115
|
+
msgstr ""
|
|
116
|
+
|
|
117
|
+
msgid "ItemModel.category.verbose_name"
|
|
118
|
+
msgstr ""
|
|
119
|
+
|
|
120
|
+
msgid "ItemModel.category.help_text"
|
|
121
|
+
msgstr " "
|
|
122
|
+
|
|
105
123
|
msgid "ItemModel.kind.verbose_name"
|
|
106
124
|
msgstr "Tipos"
|
|
107
125
|
|
|
@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
|
|
|
7
7
|
from django.core.management.base import BaseCommand
|
|
8
8
|
|
|
9
9
|
from inventory.models import ItemModel, LocationModel
|
|
10
|
+
from inventory.models.item import ItemMainCategory
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
SEED_DATA_USER_PREFIX = 'seed-data-user-'
|
|
@@ -46,7 +47,8 @@ def iter_location_chain(user, location_count):
|
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
class ItemCreator:
|
|
49
|
-
def __init__(self):
|
|
50
|
+
def __init__(self, categories: list[ItemMainCategory]):
|
|
51
|
+
self.categories = itertools.cycle(categories)
|
|
50
52
|
self.equipment_no = itertools.count(start=1)
|
|
51
53
|
self.item_no = itertools.count(start=1)
|
|
52
54
|
self.part_no = itertools.count(start=1)
|
|
@@ -57,10 +59,13 @@ class ItemCreator:
|
|
|
57
59
|
assert user
|
|
58
60
|
assert location
|
|
59
61
|
while True:
|
|
62
|
+
category = next(self.categories)
|
|
63
|
+
|
|
60
64
|
equipment = ItemModel.objects.create(
|
|
61
65
|
user=user,
|
|
66
|
+
category=category,
|
|
62
67
|
location=location,
|
|
63
|
-
name=f'
|
|
68
|
+
name=f'{category.name} {next(self.equipment_no):03}',
|
|
64
69
|
)
|
|
65
70
|
equipment.full_clean()
|
|
66
71
|
yield equipment
|
|
@@ -68,6 +73,7 @@ class ItemCreator:
|
|
|
68
73
|
while True:
|
|
69
74
|
item = ItemModel.objects.create(
|
|
70
75
|
user=user,
|
|
76
|
+
category=category,
|
|
71
77
|
location=location,
|
|
72
78
|
name=f'Item {next(self.item_no):03}',
|
|
73
79
|
parent=equipment,
|
|
@@ -78,6 +84,7 @@ class ItemCreator:
|
|
|
78
84
|
while True:
|
|
79
85
|
part = ItemModel.objects.create(
|
|
80
86
|
user=user,
|
|
87
|
+
category=category,
|
|
81
88
|
location=location,
|
|
82
89
|
name=f'Part {next(self.part_no):03}',
|
|
83
90
|
parent=item,
|
|
@@ -89,6 +96,14 @@ class ItemCreator:
|
|
|
89
96
|
return
|
|
90
97
|
|
|
91
98
|
|
|
99
|
+
def create_categories() -> list[ItemMainCategory]:
|
|
100
|
+
categories = []
|
|
101
|
+
for category in ('Retrocomputing', 'Photo Equipment', 'Household Goods'):
|
|
102
|
+
instance = ItemMainCategory.objects.get_or_create(name=category)[0]
|
|
103
|
+
categories.append(instance)
|
|
104
|
+
return categories
|
|
105
|
+
|
|
106
|
+
|
|
92
107
|
class Command(BaseCommand):
|
|
93
108
|
help = 'Fill database with example data'
|
|
94
109
|
|
|
@@ -111,13 +126,15 @@ class Command(BaseCommand):
|
|
|
111
126
|
log_level = logging.WARNING
|
|
112
127
|
|
|
113
128
|
with SetupLogger(level=log_level):
|
|
129
|
+
categories = create_categories()
|
|
130
|
+
|
|
114
131
|
existing_users = User.objects.filter(username__startswith=SEED_DATA_USER_PREFIX)
|
|
115
132
|
for user in existing_users:
|
|
116
133
|
self.stdout.write(f'Clean data from user {user}...')
|
|
117
134
|
info = user.delete()
|
|
118
135
|
self.stdout.write(f'done: {info}')
|
|
119
136
|
|
|
120
|
-
item_creator = ItemCreator()
|
|
137
|
+
item_creator = ItemCreator(categories)
|
|
121
138
|
|
|
122
139
|
for user_no in range(1, user_count + 1):
|
|
123
140
|
self.stdout.write('_' * 100)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by Django 5.1.12 on 2025-10-16 08:44
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('inventory', '0014_alter_itemmodel_description_and_more'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.CreateModel(
|
|
15
|
+
name='ItemMainCategory',
|
|
16
|
+
fields=[
|
|
17
|
+
('id', models.SmallAutoField(primary_key=True, serialize=False)),
|
|
18
|
+
('name', models.CharField(help_text='ItemMainCategory.name.help_text', max_length=32, unique=True, verbose_name='ItemMainCategory.name.verbose_name')),
|
|
19
|
+
('order', models.SmallIntegerField(default=0)),
|
|
20
|
+
],
|
|
21
|
+
options={
|
|
22
|
+
'verbose_name': 'ItemMainCategory.verbose_name',
|
|
23
|
+
'verbose_name_plural': 'ItemMainCategory.verbose_name_plural',
|
|
24
|
+
'ordering': ('order', 'name'),
|
|
25
|
+
},
|
|
26
|
+
),
|
|
27
|
+
migrations.AddField(
|
|
28
|
+
model_name='itemmodel',
|
|
29
|
+
name='category',
|
|
30
|
+
field=models.ForeignKey(blank=True, help_text='ItemModel.category.help_text', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='items', to='inventory.itemmaincategory', verbose_name='ItemModel.category.verbose_name'),
|
|
31
|
+
),
|
|
32
|
+
]
|
|
@@ -17,6 +17,29 @@ from inventory.models.links import BaseLink
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
class ItemMainCategory(models.Model):
|
|
21
|
+
id = models.SmallAutoField(primary_key=True)
|
|
22
|
+
name = models.CharField(
|
|
23
|
+
max_length=32,
|
|
24
|
+
unique=True,
|
|
25
|
+
verbose_name=_('ItemMainCategory.name.verbose_name'),
|
|
26
|
+
help_text=_('ItemMainCategory.name.help_text'),
|
|
27
|
+
)
|
|
28
|
+
order = models.SmallIntegerField(
|
|
29
|
+
default=0,
|
|
30
|
+
blank=False,
|
|
31
|
+
null=False,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def __str__(self):
|
|
35
|
+
return self.name
|
|
36
|
+
|
|
37
|
+
class Meta:
|
|
38
|
+
ordering = ('order', 'name')
|
|
39
|
+
verbose_name = _('ItemMainCategory.verbose_name')
|
|
40
|
+
verbose_name_plural = _('ItemMainCategory.verbose_name_plural')
|
|
41
|
+
|
|
42
|
+
|
|
20
43
|
class ItemQuerySet(models.QuerySet):
|
|
21
44
|
def sort(self):
|
|
22
45
|
return self.order_by('kind', 'producer', 'name')
|
|
@@ -29,6 +52,16 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
|
|
29
52
|
|
|
30
53
|
objects = ItemQuerySet.as_manager()
|
|
31
54
|
|
|
55
|
+
category = models.ForeignKey(
|
|
56
|
+
ItemMainCategory,
|
|
57
|
+
null=True,
|
|
58
|
+
blank=True,
|
|
59
|
+
on_delete=models.PROTECT,
|
|
60
|
+
related_name='items',
|
|
61
|
+
verbose_name=_('ItemModel.category.verbose_name'),
|
|
62
|
+
help_text=_('ItemModel.category.help_text'),
|
|
63
|
+
)
|
|
64
|
+
|
|
32
65
|
kind = tagulous.models.TagField(
|
|
33
66
|
case_sensitive=False,
|
|
34
67
|
force_lowercase=False,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from django.contrib import admin
|
|
4
|
+
from django.core.cache import cache
|
|
5
|
+
from django.db.models.options import Options
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
CURRENT_CATEGORY_CACHE_KEY_PREFIX = 'persistent_parameter'
|
|
12
|
+
CURRENT_CATEGORY_CACHE_TIMEOUT = 60 * 60 * 24 * 14 # 2 weeks
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def persistent_parameter(request, opts: Options, parameter_name: str):
|
|
16
|
+
cache_key = (
|
|
17
|
+
f'{CURRENT_CATEGORY_CACHE_KEY_PREFIX}_{request.user.pk}_{opts.app_label}_{opts.model_name}_{parameter_name}'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Collect from GET:
|
|
21
|
+
if parameter_name in request.GET:
|
|
22
|
+
current_value = request.GET[parameter_name] or None
|
|
23
|
+
logger.debug('Store %r to %r', current_value, cache_key)
|
|
24
|
+
cache.set(cache_key, current_value, timeout=CURRENT_CATEGORY_CACHE_TIMEOUT)
|
|
25
|
+
return current_value
|
|
26
|
+
|
|
27
|
+
# Try to restore from cache:
|
|
28
|
+
current_value = cache.get(cache_key)
|
|
29
|
+
logger.debug('Restore %r from %r', current_value, cache_key)
|
|
30
|
+
return current_value
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class PersistentRelatedFieldListFilter(admin.RelatedFieldListFilter):
|
|
34
|
+
"""
|
|
35
|
+
Stores the last filter value in the cache and restores it on next visit.
|
|
36
|
+
Note: Will not restore "is null" filter state!
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, field, request, params, model, model_admin, field_path):
|
|
40
|
+
opts: Options = model._meta
|
|
41
|
+
super().__init__(field, request, params, model, model_admin, field_path)
|
|
42
|
+
|
|
43
|
+
current_parameter = persistent_parameter(request, opts, parameter_name=self.lookup_kwarg)
|
|
44
|
+
if current_parameter and not self.lookup_val:
|
|
45
|
+
logger.info('Restore %r filter for %s with %r', field_path, opts.model_name, current_parameter)
|
|
46
|
+
self.lookup_val = [current_parameter]
|
|
47
|
+
self.used_parameters = {self.lookup_kwarg: self.lookup_val}
|