kopia lustrzana https://github.com/jedie/PyInventory
Fix #75 protect overwriting a new version with a older one
Protect Item, Location and Memo model overwriting a new version with a older one. Add a auto increment "version" number field to these models and check this on every save call... Fix: https://github.com/jedie/PyInventory/issues/75 Use new VersionProtectBaseModel from django-tools: https://github.com/jedie/django-tools/tree/master/django_tools/model_version_protectpull/78/head
rodzic
42d492ccf4
commit
308b68e97f
|
@ -1,3 +1,3 @@
|
|||
export PROJECT_NAME=pyinventory
|
||||
export PROJECT_PACKAGE_NAME=pyinventory
|
||||
export PROJECT_VERSION=0.11.0
|
||||
export PROJECT_VERSION=0.12.0.rc1
|
||||
|
|
|
@ -123,7 +123,7 @@ webencodings = "*"
|
|||
|
||||
[[package]]
|
||||
name = "bx-django-utils"
|
||||
version = "9"
|
||||
version = "11"
|
||||
description = "Various Django utility functions"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -271,7 +271,7 @@ yaml = ["PyYAML (>=3.10)"]
|
|||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "35.0.0"
|
||||
version = "36.0.0"
|
||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -282,7 +282,7 @@ cffi = ">=1.12"
|
|||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"]
|
||||
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
|
||||
docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
|
||||
pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
|
||||
sdist = ["setuptools_rust (>=0.11.4)"]
|
||||
ssh = ["bcrypt (>=3.1.5)"]
|
||||
|
@ -374,7 +374,7 @@ django-ipware = ">=3,<5"
|
|||
|
||||
[[package]]
|
||||
name = "django-ckeditor"
|
||||
version = "6.1.0"
|
||||
version = "6.2.0"
|
||||
description = "Django admin CKEditor integration."
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -488,14 +488,15 @@ devdb = ["psycopg2", "mysqlclient"]
|
|||
|
||||
[[package]]
|
||||
name = "django-tools"
|
||||
version = "0.48.3"
|
||||
description = "miscellaneous tools for django"
|
||||
version = "0.49.0"
|
||||
description = "miscellaneous tools for Django based projects"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0.0"
|
||||
python-versions = ">=3.7,<4.0.0"
|
||||
|
||||
[package.dependencies]
|
||||
bleach = "*"
|
||||
bx_py_utils = "*"
|
||||
django = "*"
|
||||
icdiff = "*"
|
||||
pprintpp = "*"
|
||||
|
@ -1289,7 +1290,7 @@ jeepney = ">=0.6"
|
|||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
version = "4.0.0"
|
||||
version = "4.1.0"
|
||||
description = ""
|
||||
category = "dev"
|
||||
optional = false
|
||||
|
@ -1620,7 +1621,7 @@ psycopg2-source = ["psycopg2"]
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = ">=3.7,<4.0.0"
|
||||
content-hash = "5eaa826b474da770088d7ca448725afc339023a9ff5493e8496a4f878c844148"
|
||||
content-hash = "8ecba73cd2070b4092c88aa7219d6dfcbea4133a904b401d80a8b491cf08c187"
|
||||
|
||||
[metadata.files]
|
||||
asgiref = [
|
||||
|
@ -1669,8 +1670,8 @@ bleach = [
|
|||
{file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"},
|
||||
]
|
||||
bx-django-utils = [
|
||||
{file = "bx_django_utils-9-py3-none-any.whl", hash = "sha256:3c5e7710abc7084fce567e16c85b598ebd69e5068b426a94935ce7c6e679f4e7"},
|
||||
{file = "bx_django_utils-9.tar.gz", hash = "sha256:6acd8e41e18915335aff5aedd71693ff8cc8e99d15cbc37a30c9f25fa4b71eaa"},
|
||||
{file = "bx_django_utils-11-py3-none-any.whl", hash = "sha256:b4115fbffb5b788e3ed6c13f5aa9d87991da35f1235de4376ca3e780d03546e9"},
|
||||
{file = "bx_django_utils-11.tar.gz", hash = "sha256:a7549c6fd6b9a745e8949c6dfede825433d532c907e86140b7b8fb19cb63945c"},
|
||||
]
|
||||
bx-py-utils = [
|
||||
{file = "bx_py_utils-50-py3-none-any.whl", hash = "sha256:3713ee75904c061eb934d2ab7a842760a8e0fb99db3b69ff5bd6841aa9ef04ae"},
|
||||
|
@ -1810,26 +1811,27 @@ coveralls = [
|
|||
{file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"},
|
||||
]
|
||||
cryptography = [
|
||||
{file = "cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-win32.whl", hash = "sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8"},
|
||||
{file = "cryptography-35.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588"},
|
||||
{file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953"},
|
||||
{file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6"},
|
||||
{file = "cryptography-35.0.0-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd"},
|
||||
{file = "cryptography-35.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"},
|
||||
{file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999"},
|
||||
{file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad"},
|
||||
{file = "cryptography-35.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2"},
|
||||
{file = "cryptography-35.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c"},
|
||||
{file = "cryptography-35.0.0.tar.gz", hash = "sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:9511416e85e449fe1de73f7f99b21b3aa04fba4c4d335d30c486ba3756e3a2a6"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:97199a13b772e74cdcdb03760c32109c808aff7cd49c29e9cf4b7754bb725d1d"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:494106e9cd945c2cadfce5374fa44c94cfadf01d4566a3b13bb487d2e6c7959e"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6fbbbb8aab4053fa018984bb0e95a16faeb051dd8cca15add2a27e267ba02b58"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:684993ff6f67000a56454b41bdc7e015429732d65a52d06385b6e9de6181c71e"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c702855cd3174666ef0d2d13dcc879090aa9c6c38f5578896407a7028f75b9f"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d91bc9f535599bed58f6d2e21a2724cb0c3895bf41c6403fe881391d29096f1d"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:b17d83b3d1610e571fedac21b2eb36b816654d6f7496004d6a0d32f99d1d8120"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8982c19bb90a4fa2aad3d635c6d71814e38b643649b4000a8419f8691f20ac44"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:24469d9d33217ffd0ce4582dfcf2a76671af115663a95328f63c99ec7ece61a4"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-win32.whl", hash = "sha256:f6a5a85beb33e57998dc605b9dbe7deaa806385fdf5c4810fb849fcd04640c81"},
|
||||
{file = "cryptography-36.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:2deab5ec05d83ddcf9b0916319674d3dae88b0e7ee18f8962642d3cde0496568"},
|
||||
{file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2049f8b87f449fc6190350de443ee0c1dd631f2ce4fa99efad2984de81031681"},
|
||||
{file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a776bae1629c8d7198396fd93ec0265f8dd2341c553dc32b976168aaf0e6a636"},
|
||||
{file = "cryptography-36.0.0-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:aa94d617a4cd4cdf4af9b5af65100c036bce22280ebb15d8b5262e8273ebc6ba"},
|
||||
{file = "cryptography-36.0.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:5c49c9e8fb26a567a2b3fa0343c89f5d325447956cc2fc7231c943b29a973712"},
|
||||
{file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef216d13ac8d24d9cd851776662f75f8d29c9f2d05cdcc2d34a18d32463a9b0b"},
|
||||
{file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:231c4a69b11f6af79c1495a0e5a85909686ea8db946935224b7825cfb53827ed"},
|
||||
{file = "cryptography-36.0.0-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:f92556f94e476c1b616e6daec5f7ddded2c082efa7cee7f31c7aeda615906ed8"},
|
||||
{file = "cryptography-36.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d73e3a96c38173e0aa5646c31bf8473bc3564837977dd480f5cbeacf1d7ef3a3"},
|
||||
{file = "cryptography-36.0.0.tar.gz", hash = "sha256:52f769ecb4ef39865719aedc67b4b7eae167bafa48dbc2a26dd36fa56460507f"},
|
||||
]
|
||||
defusedxml = [
|
||||
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
||||
|
@ -1864,8 +1866,8 @@ django-axes = [
|
|||
{file = "django_axes-5.27.0-py3-none-any.whl", hash = "sha256:e6ac2266626d4e52a44939bdb861817766f127efe110c8e8ce2a776270954926"},
|
||||
]
|
||||
django-ckeditor = [
|
||||
{file = "django-ckeditor-6.1.0.tar.gz", hash = "sha256:f0d108f67a81a04e26d8de11255fe314f51026eaf8eb0534a807512ae3c21620"},
|
||||
{file = "django_ckeditor-6.1.0-py2.py3-none-any.whl", hash = "sha256:346b26b9d60dc8a88524d0eaaf406f4e91a4b3c22d208ae87aa032bf500b251c"},
|
||||
{file = "django-ckeditor-6.2.0.tar.gz", hash = "sha256:df64dc9e62790ef824f609605d31be847bdbce1cc7aa94e49bd5ca60d7aa79bb"},
|
||||
{file = "django_ckeditor-6.2.0-py2.py3-none-any.whl", hash = "sha256:9f66420907e41f5b4e698fa5671a00a86995776735f2c4696174aed4640fcbd8"},
|
||||
]
|
||||
django-dbbackup = [
|
||||
{file = "django-dbbackup-3.3.0.tar.gz", hash = "sha256:bb109735cae98b64ad084e5b461b7aca2d7b39992f10c9ed9435e3ebb6fb76c8"},
|
||||
|
@ -1903,8 +1905,8 @@ django-tagulous = [
|
|||
{file = "django_tagulous-1.3.0-py3-none-any.whl", hash = "sha256:2da8fd03d466fea6769e44df774c69d214b95eec2b6e9b7c6073309bc8781c72"},
|
||||
]
|
||||
django-tools = [
|
||||
{file = "django-tools-0.48.3.tar.gz", hash = "sha256:08ed2ae606067f49c2c3949055227a826c8b880e5816114925eca386cf1823af"},
|
||||
{file = "django_tools-0.48.3-py3-none-any.whl", hash = "sha256:40444fa16b703b7c6960a800ba76aad42472c9aa70040d549a4d91dbb47a5ddb"},
|
||||
{file = "django-tools-0.49.0.tar.gz", hash = "sha256:9da6d5610576a34219be3dea9c7c2207669e5c916d89987011843ded772ece0a"},
|
||||
{file = "django_tools-0.49.0-py3-none-any.whl", hash = "sha256:a27c32cff98cd82dde23ab2f05fb9e06a32aaeb8357e96f1ec02a634b6619170"},
|
||||
]
|
||||
docker = [
|
||||
{file = "docker-5.0.3-py2.py3-none-any.whl", hash = "sha256:7a79bb439e3df59d0a72621775d600bc8bc8b422d285824cb37103eab91d1ce0"},
|
||||
|
@ -2391,7 +2393,7 @@ secretstorage = [
|
|||
{file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"},
|
||||
]
|
||||
selenium = [
|
||||
{file = "selenium-4.0.0-py3-none-any.whl", hash = "sha256:c942b166a21ce9c9065ad249b54059e926d39f9000167b5ca0fa4950d2ef9a82"},
|
||||
{file = "selenium-4.1.0-py3-none-any.whl", hash = "sha256:27e7b64df961d609f3d57237caa0df123abbbe22d038f2ec9e332fb90ec1a939"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "PyInventory"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0.rc1"
|
||||
description = "Web based management to catalog things including state and location etc. using Python/Django."
|
||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
||||
homepage = "https://github.com/jedie/PyInventory"
|
||||
|
@ -43,7 +43,7 @@ django-processinfo = "*" # https://github.com/jedie/django-processinfo/
|
|||
django-debug-toolbar = "*" # http://django-debug-toolbar.readthedocs.io/en/stable/changes.html
|
||||
django-import-export = "*" # https://github.com/django-import-export/django-import-export
|
||||
django-dbbackup = "*" # https://github.com/django-dbbackup/django-dbbackup
|
||||
django-tools = ">=0.48.2" # https://github.com/jedie/django-tools/
|
||||
django-tools = ">=0.49.0" # https://github.com/jedie/django-tools/
|
||||
django-reversion-compare = "*" # https://github.com/jedie/django-reversion-compare/
|
||||
django-ckeditor = "*" # https://github.com/django-ckeditor/django-ckeditor
|
||||
bx_py_utils = "*" # https://github.com/boxine/bx_py_utils
|
||||
|
|
|
@ -4,7 +4,4 @@
|
|||
:license: GNU GPL v3 or above, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
__version__ = "0.11.0"
|
||||
|
||||
# https://docs.djangoproject.com/en/2.0/ref/applications/#configuring-applications-ref
|
||||
default_app_config = "inventory.apps.InventoryConfig"
|
||||
__version__ = "0.12.0.rc1"
|
||||
|
|
|
@ -124,7 +124,7 @@ class ItemModelAdmin(ImportExportMixin, BaseUserAdmin):
|
|||
(_('Internals'), {
|
||||
'classes': ('collapse',),
|
||||
'fields': (
|
||||
'id',
|
||||
('id', 'version'),
|
||||
'user',
|
||||
)
|
||||
}),
|
||||
|
|
|
@ -47,7 +47,7 @@ class MemoModelAdmin(ImportExportMixin, BaseUserAdmin):
|
|||
(_('Internals'), {
|
||||
'classes': ('collapse',),
|
||||
'fields': (
|
||||
'id',
|
||||
('id', 'version'),
|
||||
'user',
|
||||
)
|
||||
}),
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 3.1.13 on 2021-11-22 17:47
|
||||
|
||||
from django.db import migrations
|
||||
import django_tools.model_version_protect.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0009_add_memo'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='itemmodel',
|
||||
name='version',
|
||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='locationmodel',
|
||||
name='version',
|
||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='memomodel',
|
||||
name='version',
|
||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
||||
),
|
||||
]
|
|
@ -7,6 +7,7 @@ from ckeditor_uploader.fields import RichTextUploadingField
|
|||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tools.model_version_protect.models import VersionProtectBaseModel
|
||||
from django_tools.serve_media_app.models import user_directory_path
|
||||
|
||||
from inventory.models.base import BaseItemAttachmentModel, BaseModel
|
||||
|
@ -21,7 +22,7 @@ class ItemQuerySet(models.QuerySet):
|
|||
return self.order_by('kind', 'producer', 'name')
|
||||
|
||||
|
||||
class ItemModel(BaseModel):
|
||||
class ItemModel(BaseModel, VersionProtectBaseModel):
|
||||
"""
|
||||
A Item that can be described and store somewhere ;)
|
||||
"""
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from ckeditor_uploader.fields import RichTextUploadingField
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tools.model_version_protect.models import VersionProtectBaseModel
|
||||
|
||||
from inventory.models.base import BaseModel
|
||||
|
||||
|
||||
class LocationModel(BaseModel):
|
||||
class LocationModel(BaseModel, VersionProtectBaseModel):
|
||||
"""
|
||||
A Storage for items.
|
||||
"""
|
||||
|
|
|
@ -6,6 +6,7 @@ from ckeditor_uploader.fields import RichTextUploadingField
|
|||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_tools.model_version_protect.models import VersionProtectBaseModel
|
||||
from django_tools.serve_media_app.models import user_directory_path
|
||||
|
||||
from inventory.models.base import BaseMemoAttachmentModel, BaseModel
|
||||
|
@ -15,7 +16,7 @@ from inventory.models.links import BaseLink
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MemoModel(BaseModel):
|
||||
class MemoModel(BaseModel, VersionProtectBaseModel):
|
||||
"""
|
||||
A Memo to hold some information independ of items/location
|
||||
"""
|
||||
|
|
|
@ -80,6 +80,9 @@ INSTALLED_APPS = [
|
|||
# https://github.com/jedie/django-tools/tree/master/django_tools/serve_media_app
|
||||
'django_tools.serve_media_app.apps.UserMediaFilesConfig',
|
||||
|
||||
# https://github.com/jedie/django-tools/tree/master/django_tools/model_version_protect
|
||||
'django_tools.model_version_protect.apps.ModelVersionProtectConfig',
|
||||
|
||||
'inventory.apps.InventoryConfig',
|
||||
]
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from unittest import mock
|
|||
|
||||
from bx_django_utils.test_utils.datetime import MockDatetimeGenerator
|
||||
from bx_django_utils.test_utils.html_assertion import HtmlAssertionMixin
|
||||
from bx_py_utils.test_utils.snapshot import assert_html_snapshot
|
||||
from django.contrib.auth.models import User
|
||||
from django.template.defaulttags import CsrfTokenNode, NowNode
|
||||
from django.test import TestCase
|
||||
|
@ -17,6 +18,34 @@ from inventory.permissions import get_or_create_normal_user_group
|
|||
from inventory_project.tests.temp_utils import assert_html_response_snapshot
|
||||
|
||||
|
||||
ITEM_FORM_DEFAULTS = {
|
||||
'version': 0, # VersionProtectBaseModel field
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '0',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemimagemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemfilemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemlinkmodel_set-__prefix__-position': '0',
|
||||
|
||||
'_save': 'Save',
|
||||
}
|
||||
ITEM_FORM_DEFAULTS = tuple(ITEM_FORM_DEFAULTS.items())
|
||||
|
||||
|
||||
class AdminAnonymousTests(TestCase):
|
||||
def test_login(self):
|
||||
response = self.client.get('/admin/inventory/itemmodel/add/', HTTP_ACCEPT_LANGUAGE='en')
|
||||
|
@ -30,7 +59,8 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.normaluser = baker.make(
|
||||
User, username='NormalUser',
|
||||
User,
|
||||
id=1, username='NormalUser',
|
||||
is_staff=True, is_active=True, is_superuser=False
|
||||
)
|
||||
assert cls.normaluser.user_permissions.count() == 0
|
||||
|
@ -38,59 +68,58 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
cls.normaluser.groups.set([group])
|
||||
|
||||
def test_normal_user_create_minimal_item(self):
|
||||
self.client.force_login(self.normaluser)
|
||||
|
||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), \
|
||||
offset = datetime.timedelta(minutes=1)
|
||||
with mock.patch.object(timezone, 'now', MockDatetimeGenerator(offset=offset)),\
|
||||
mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), \
|
||||
mock.patch.object(CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'):
|
||||
self.client.force_login(self.normaluser)
|
||||
|
||||
response = self.client.get('/admin/inventory/itemmodel/add/')
|
||||
assert response.status_code == 200
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Add Item | PyInventory v{__version__}</title>',
|
||||
))
|
||||
assert_html_response_snapshot(response=response, validate=False)
|
||||
assert response.status_code == 200
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Add Item | PyInventory v{__version__}</title>',
|
||||
))
|
||||
assert_html_response_snapshot(response=response, validate=False)
|
||||
|
||||
assert ItemModel.objects.count() == 0
|
||||
assert ItemModel.objects.count() == 0
|
||||
|
||||
response = self.client.post(
|
||||
path='/admin/inventory/itemmodel/add/',
|
||||
data={
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
post_data = dict(ITEM_FORM_DEFAULTS)
|
||||
response = self.client.post(
|
||||
path='/admin/inventory/itemmodel/add/',
|
||||
data=post_data,
|
||||
)
|
||||
assert response.status_code == 302, response.content.decode('utf-8') # Form error?
|
||||
self.assertRedirects(response, expected_url='/admin/inventory/itemmodel/')
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '0',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemimagemodel_set-__prefix__-position': '0',
|
||||
data = list(ItemModel.objects.values_list('kind__name', 'name', 'version'))
|
||||
assert data == [('kind', 'name', 2)] # FIXME: Save call done two times!
|
||||
|
||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemfilemodel_set-__prefix__-position': '0',
|
||||
item = ItemModel.objects.first()
|
||||
|
||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemlinkmodel_set-__prefix__-position': '0',
|
||||
self.assert_messages(response, expected_messages=[
|
||||
f'The Item “<a href="/admin/inventory/itemmodel/{item.pk}/change/"> - name</a>”'
|
||||
' was added successfully.'
|
||||
])
|
||||
|
||||
'_save': 'Save',
|
||||
},
|
||||
)
|
||||
self.assertRedirects(response, expected_url='/admin/inventory/itemmodel/')
|
||||
assert item.user_id == self.normaluser.pk
|
||||
|
||||
data = list(ItemModel.objects.values_list('kind__name', 'name'))
|
||||
assert data == [('kind', 'name')]
|
||||
# Test django-tools VersionProtectBaseModel integration:
|
||||
|
||||
item = ItemModel.objects.first()
|
||||
|
||||
self.assert_messages(response, expected_messages=[
|
||||
f'The Item “<a href="/admin/inventory/itemmodel/{item.pk}/change/"> - name</a>”'
|
||||
' was added successfully.'
|
||||
])
|
||||
|
||||
assert item.user_id == self.normaluser.pk
|
||||
assert item.version == 2 # current Version in DB
|
||||
post_data['version'] = 1 # Try to overwrite with older version
|
||||
post_data['name'] = 'A new Name!'
|
||||
response = self.client.post(
|
||||
path=f'/admin/inventory/itemmodel/{item.pk}/change/',
|
||||
data=post_data,
|
||||
)
|
||||
self.assert_html_parts(response, parts=(
|
||||
f'<title>Change Item | PyInventory v{__version__}</title>',
|
||||
'<li>Version error: Overwrite version 2 with 1 is forbidden!</li>',
|
||||
'<pre>- "name"\n+ "A new Name!"</pre>'
|
||||
))
|
||||
html = response.content.decode('utf-8')
|
||||
html = html.replace(str(item.pk), '<removed-UUID>')
|
||||
assert_html_snapshot(got=html, validate=False)
|
||||
|
||||
def test_new_item_with_image(self):
|
||||
"""
|
||||
|
@ -100,34 +129,16 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
|
||||
img = ImageDummy(width=1, height=1, format='png').in_memory_image_file(filename='test.png')
|
||||
|
||||
post_data = dict(ITEM_FORM_DEFAULTS)
|
||||
post_data.update({
|
||||
'itemimagemodel_set-TOTAL_FORMS': '1',
|
||||
'itemimagemodel_set-0-position': '0',
|
||||
'itemimagemodel_set-0-image': img,
|
||||
})
|
||||
|
||||
response = self.client.post(
|
||||
path='/admin/inventory/itemmodel/add/',
|
||||
data={
|
||||
'kind': 'kind',
|
||||
'name': 'name',
|
||||
|
||||
'itemimagemodel_set-TOTAL_FORMS': '1',
|
||||
'itemimagemodel_set-INITIAL_FORMS': '0',
|
||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemimagemodel_set-0-position': '0',
|
||||
'itemimagemodel_set-__prefix__-position': '0',
|
||||
'itemimagemodel_set-0-image': img,
|
||||
|
||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemfilemodel_set-__prefix__-position': '0',
|
||||
|
||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||
'itemlinkmodel_set-__prefix__-position': '0',
|
||||
|
||||
'_save': 'Save',
|
||||
},
|
||||
data=post_data,
|
||||
)
|
||||
self.assertRedirects(response, expected_url='/admin/inventory/itemmodel/')
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Select Item to change | PyInventory v0.11.0
|
||||
Select Item to change | PyInventory v0.12.0.rc1
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/nav_sidebar.css" rel="stylesheet" type="text/css"/>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.11.0
|
||||
PyInventory v0.12.0.rc1
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Select Item to change | PyInventory v0.11.0
|
||||
Select Item to change | PyInventory v0.12.0.rc1
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/nav_sidebar.css" rel="stylesheet" type="text/css"/>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.11.0
|
||||
PyInventory v0.12.0.rc1
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Add Item | PyInventory v0.11.0
|
||||
Add Item | PyInventory v0.12.0.rc1
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/nav_sidebar.css" rel="stylesheet" type="text/css"/>
|
||||
|
@ -84,7 +84,7 @@
|
|||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.11.0
|
||||
PyInventory v0.12.0.rc1
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
@ -186,8 +186,8 @@
|
|||
<h2>
|
||||
Internals
|
||||
</h2>
|
||||
<div class="form-row field-id">
|
||||
<div>
|
||||
<div class="form-row field-id field-version">
|
||||
<div class="fieldBox field-id">
|
||||
<label>
|
||||
ID:
|
||||
</label>
|
||||
|
@ -198,6 +198,16 @@
|
|||
ID
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-version">
|
||||
<label class="required inline" for="id_version">
|
||||
Version:
|
||||
</label>
|
||||
<input id="id_version" name="version" required="" type="hidden" value="0"/>
|
||||
0
|
||||
<div class="help">
|
||||
Internal version number of this entry. Used to protect the overwriting of an older entry.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-user">
|
||||
<div>
|
||||
|
|
|
@ -0,0 +1,762 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Change Item | PyInventory v0.12.0.rc1
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/nav_sidebar.css" rel="stylesheet" type="text/css"/>
|
||||
<script defer="" src="/static/admin/js/nav_sidebar.js">
|
||||
</script>
|
||||
<link href="/static/admin/css/forms.css" rel="stylesheet" type="text/css"/>
|
||||
<meta content="notranslate" name="google"/>
|
||||
<meta content="noindex,nofollow" name="robots">
|
||||
<link href="/static/inventory.css" rel="stylesheet" type="text/css"/>
|
||||
<script src="/admin/jsi18n/">
|
||||
</script>
|
||||
<link href="/static/adminsortable2/css/sortable.css" media="all" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/vendor/select2/select2.min.css" media="screen" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/autocomplete.css" media="screen" rel="stylesheet" type="text/css"/>
|
||||
<script src="/static/admin/js/vendor/jquery/jquery.min.js">
|
||||
</script>
|
||||
<script src="/static/tagulous/tagulous.js">
|
||||
</script>
|
||||
<script data-ckeditor-basepath="/static/ckeditor/ckeditor/" id="ckeditor-init-script" src="/static/ckeditor/ckeditor-init.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/calendar.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/collapse.min.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/vendor/select2/select2.full.min.js">
|
||||
</script>
|
||||
<script src="/static/tagulous/adaptor/select2-4.js">
|
||||
</script>
|
||||
<script src="/static/ckeditor/ckeditor/ckeditor.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/admin/DateTimeShortcuts.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/vendor/select2/i18n/en.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/jquery.init.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/core.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/autocomplete.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/inlines.min.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/plugins/admincompat.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/admin/RelatedObjectLookups.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/libs/jquery.ui.core-1.11.4.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/actions.min.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/libs/jquery.ui.widget-1.11.4.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/urlify.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/libs/jquery.ui.mouse-1.11.4.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/prepopulate.min.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/libs/jquery.ui.touch-punch-0.2.3.js">
|
||||
</script>
|
||||
<script src="/static/admin/js/vendor/xregexp/xregexp.min.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/libs/jquery.ui.sortable-1.11.4.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/inline-sortable.js">
|
||||
</script>
|
||||
<script src="/static/adminsortable2/js/inline-tabular.js">
|
||||
</script>
|
||||
<meta content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" name="viewport"/>
|
||||
<link href="/static/admin/css/responsive.css" rel="stylesheet" type="text/css"/>
|
||||
<meta content="NONE,NOARCHIVE" name="robots"/>
|
||||
</meta>
|
||||
</head>
|
||||
<body class="app-inventory model-itemmodel change-form" data-admin-utc-offset="MockedNowNode">
|
||||
<!-- Container -->
|
||||
<div id="container">
|
||||
<!-- Header -->
|
||||
<div id="header">
|
||||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.12.0.rc1
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="user-tools">
|
||||
Welcome,
|
||||
<strong>
|
||||
NormalUser
|
||||
</strong>
|
||||
.
|
||||
<a href="/">
|
||||
View site
|
||||
</a>
|
||||
/
|
||||
<a href="/admin/password_change/">
|
||||
Change password
|
||||
</a>
|
||||
/
|
||||
<a href="/admin/logout/">
|
||||
Log out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END Header -->
|
||||
<div class="breadcrumbs">
|
||||
<a href="/admin/">
|
||||
Home
|
||||
</a>
|
||||
›
|
||||
<a href="/admin/inventory/">
|
||||
Inventory
|
||||
</a>
|
||||
›
|
||||
<a href="/admin/inventory/itemmodel/">
|
||||
Items
|
||||
</a>
|
||||
› - A new Name!
|
||||
</div>
|
||||
<div class="main shifted" id="main">
|
||||
<button aria-label="Toggle navigation" class="sticky toggle-nav-sidebar" id="toggle-nav-sidebar">
|
||||
</button>
|
||||
<nav class="sticky" id="nav-sidebar">
|
||||
<div class="app-inventory module current-app">
|
||||
<table>
|
||||
<caption>
|
||||
<a class="section" href="/admin/inventory/" title="Models in the Inventory application">
|
||||
Inventory
|
||||
</a>
|
||||
</caption>
|
||||
<tr class="model-itemmodel current-model">
|
||||
<th scope="row">
|
||||
<a aria-current="page" href="/admin/inventory/itemmodel/">
|
||||
Items
|
||||
</a>
|
||||
</th>
|
||||
<td>
|
||||
<a class="addlink" href="/admin/inventory/itemmodel/add/">
|
||||
Add
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="model-locationmodel">
|
||||
<th scope="row">
|
||||
<a href="/admin/inventory/locationmodel/">
|
||||
Locations
|
||||
</a>
|
||||
</th>
|
||||
<td>
|
||||
<a class="addlink" href="/admin/inventory/locationmodel/add/">
|
||||
Add
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="model-memomodel">
|
||||
<th scope="row">
|
||||
<a href="/admin/inventory/memomodel/">
|
||||
Memos
|
||||
</a>
|
||||
</th>
|
||||
<td>
|
||||
<a class="addlink" href="/admin/inventory/memomodel/add/">
|
||||
Add
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="content">
|
||||
<!-- Content -->
|
||||
<div class="colM" id="content">
|
||||
<h1>
|
||||
Change Item
|
||||
</h1>
|
||||
<div id="content-main">
|
||||
<ul class="object-tools">
|
||||
<li>
|
||||
<a class="historylink" href="/admin/inventory/itemmodel/<removed-UUID>/history/">
|
||||
History
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form enctype="multipart/form-data" id="itemmodel_form" method="post" novalidate="">
|
||||
MockedCsrfTokenNode
|
||||
<div>
|
||||
<p class="errornote">
|
||||
Please correct the errors below.
|
||||
</p>
|
||||
<ul class="errorlist nonfield">
|
||||
<li>
|
||||
Version error: Overwrite version 2 with 1 is forbidden!
|
||||
</li>
|
||||
</ul>
|
||||
<fieldset class="module aligned collapse">
|
||||
<h2>
|
||||
Internals
|
||||
</h2>
|
||||
<div class="form-row field-id field-version">
|
||||
<div class="fieldBox field-id">
|
||||
<label>
|
||||
ID:
|
||||
</label>
|
||||
<div class="readonly">
|
||||
<removed-uuid>
|
||||
</removed-uuid>
|
||||
</div>
|
||||
<div class="help">
|
||||
ID
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-version errors">
|
||||
<ul class="errorlist">
|
||||
<li>
|
||||
Version changed:
|
||||
<pre>- 2
|
||||
+ 1</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="required inline" for="id_version">
|
||||
Version:
|
||||
</label>
|
||||
<input id="id_version" name="version" required="" type="hidden" value="1"/>
|
||||
1
|
||||
<div class="help">
|
||||
Internal version number of this entry. Used to protect the overwriting of an older entry.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-user">
|
||||
<div>
|
||||
<label>
|
||||
User:
|
||||
</label>
|
||||
<div class="readonly">
|
||||
NormalUser
|
||||
</div>
|
||||
<div class="help">
|
||||
The user who is the owner of this entry and can manage it (will be set automatically)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="module aligned collapse">
|
||||
<h2>
|
||||
Meta
|
||||
</h2>
|
||||
<div class="form-row field-create_dt">
|
||||
<div>
|
||||
<label>
|
||||
Create date:
|
||||
</label>
|
||||
<div class="readonly">
|
||||
Jan. 1, 2000, 1:16 a.m.
|
||||
</div>
|
||||
<div class="help">
|
||||
(will be set automatically)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-update_dt">
|
||||
<div>
|
||||
<label>
|
||||
Last update:
|
||||
</label>
|
||||
<div class="readonly">
|
||||
Jan. 1, 2000, 1:17 a.m.
|
||||
</div>
|
||||
<div class="help">
|
||||
(will be set automatically)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="module aligned">
|
||||
<h2>
|
||||
Basic
|
||||
</h2>
|
||||
<div class="form-row field-kind">
|
||||
<div>
|
||||
<label class="required" for="id_kind">
|
||||
Kind:
|
||||
</label>
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list='["kind"]' data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 3, "space_delimiter": false, "required": true}' data-tagulous="true" data-theme="admin-autocomplete" id="id_kind" name="kind" required="" type="text" value="kind"/>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-producer field-name">
|
||||
<div class="fieldBox field-producer">
|
||||
<label for="id_producer">
|
||||
Producer:
|
||||
</label>
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list="[]" data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 1, "space_delimiter": false, "required": false}' data-tagulous="true" data-theme="admin-autocomplete" id="id_producer" name="producer" type="text"/>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-name errors">
|
||||
<ul class="errorlist">
|
||||
<li>
|
||||
changes between version 2 and 1:
|
||||
<pre>- "name"
|
||||
+ "A new Name!"</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="required inline" for="id_name">
|
||||
Name:
|
||||
</label>
|
||||
<input class="vTextField" id="id_name" maxlength="255" name="name" required="" type="text" value="A new Name!"/>
|
||||
<div class="help">
|
||||
Name
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-description">
|
||||
<div>
|
||||
<label for="id_description">
|
||||
Description:
|
||||
</label>
|
||||
<div class="django-ckeditor-widget" data-field-id="id_description" style="display: inline-block;">
|
||||
<textarea cols="40" data-config='{"skin": "moono-lisa", "toolbar_Basic": [["Source", "-", "Bold", "Italic"]], "toolbar_Full": [["Styles", "Format", "Bold", "Italic", "Underline", "Strike", "SpellChecker", "Undo", "Redo"], ["Link", "Unlink", "Anchor"], ["Image", "Flash", "Table", "HorizontalRule"], ["TextColor", "BGColor"], ["Smiley", "SpecialChar"], ["Source"]], "toolbar": "PyInventoryToolbarConfig", "height": "25em", "width": "100%", "filebrowserWindowWidth": 940, "filebrowserWindowHeight": 725, "removeButtons": "Language,Cut,Copy,Paste,Undo,Redo,Anchor", "removePlugins": ["a11yhelp", "adobeair", "ajax", "autoembed", "autolink", "bbcode", "bidi", "clipboard", "codesnippet", "codesnippetgeshi", "contextmenu", "copyformatting", "devtools", "dialog", "dialogadvtab", "div", "divarea", "docprops", "embed", "embedbase", "embedsemantic", "enterkey", "exportpdf", "find", "flash", "forms", "htmlwriter", "iframe", "iframedialog", "language", "magicline", "mathjax", "newpage", "notification", "notificationaggregator", "pagebreak", "pastefromgdocs", "pastefromword", "pastetext", "pastetools", "placeholder", "preview", "print", "save", "scayt", "selectall", "sharedspace", "smiley", "sourcedialog", "specialchar", "stylescombo", "stylesheetparser", "tab", "templates", "uicolor", "widget", "wsc", "xml"], "toolbar_PyInventoryToolbarConfig": [{"name": "basicstyles", "items": ["Bold", "Italic", "Underline", "Strike", "-", "RemoveFormat"]}, {"name": "paragraph", "items": ["NumberedList", "BulletedList", "-", "Outdent", "Indent", "-", "Blockquote", "-", "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"]}, {"name": "links", "items": ["Link", "Unlink", "Anchor"]}, {"name": "insert", "items": ["Image", "Table", "HorizontalRule"]}, "/", {"name": "styles", "items": ["Styles", "Format", "Font", "FontSize"]}, {"name": "colors", "items": ["TextColor", "BGColor"]}, {"name": "tools", "items": ["Maximize", "ShowBlocks", "Source"]}, {"name": "about", "items": ["About"]}], "filebrowserUploadUrl": "/ckeditor/upload/", "filebrowserBrowseUrl": "/ckeditor/browse/", "language": "en"}' data-external-plugin-resources="[]" data-id="id_description" data-processed="0" data-type="ckeditortype" id="id_description" name="description" rows="10"></textarea>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-tags">
|
||||
<div>
|
||||
<label for="id_tags">
|
||||
Tags:
|
||||
</label>
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list="[]" data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 10, "space_delimiter": false, "required": false}' data-tagulous="true" data-theme="admin-autocomplete" id="id_tags" name="tags" type="text"/>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-fcc_id">
|
||||
<div>
|
||||
<label for="id_fcc_id">
|
||||
FCC ID:
|
||||
</label>
|
||||
<input class="vTextField" id="id_fcc_id" maxlength="20" name="fcc_id" type="text"/>
|
||||
<div class="help">
|
||||
Unique number from the FCC
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-parent">
|
||||
<div>
|
||||
<label for="id_parent">
|
||||
Parent:
|
||||
</label>
|
||||
<div class="related-widget-wrapper">
|
||||
<select id="id_parent" name="parent">
|
||||
<option selected="" value="">
|
||||
---------
|
||||
</option>
|
||||
<option value="<removed-UUID>">
|
||||
- name
|
||||
</option>
|
||||
</select>
|
||||
<a class="related-widget-wrapper-link change-related" data-href-template="/admin/inventory/itemmodel/__fk__/change/?_to_field=id&_popup=1" id="change_id_parent" title="Change selected Item">
|
||||
<img alt="Change" src="/static/admin/img/icon-changelink.svg"/>
|
||||
</a>
|
||||
<a class="related-widget-wrapper-link add-related" href="/admin/inventory/itemmodel/add/?_to_field=id&_popup=1" id="add_id_parent" title="Add another Item">
|
||||
<img alt="Add" src="/static/admin/img/icon-addlink.svg"/>
|
||||
</a>
|
||||
<a class="related-widget-wrapper-link delete-related" data-href-template="/admin/inventory/itemmodel/__fk__/delete/?_to_field=id&_popup=1" id="delete_id_parent" title="Delete selected Item">
|
||||
<img alt="Delete" src="/static/admin/img/icon-deletelink.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-location">
|
||||
<div>
|
||||
<label for="id_location">
|
||||
Location:
|
||||
</label>
|
||||
<div class="related-widget-wrapper">
|
||||
<select id="id_location" name="location">
|
||||
<option selected="" value="">
|
||||
---------
|
||||
</option>
|
||||
</select>
|
||||
<a class="related-widget-wrapper-link change-related" data-href-template="/admin/inventory/locationmodel/__fk__/change/?_to_field=id&_popup=1" id="change_id_location" title="Change selected Location">
|
||||
<img alt="Change" src="/static/admin/img/icon-changelink.svg"/>
|
||||
</a>
|
||||
<a class="related-widget-wrapper-link add-related" href="/admin/inventory/locationmodel/add/?_to_field=id&_popup=1" id="add_id_location" title="Add another Location">
|
||||
<img alt="Add" src="/static/admin/img/icon-addlink.svg"/>
|
||||
</a>
|
||||
<a class="related-widget-wrapper-link delete-related" data-href-template="/admin/inventory/locationmodel/__fk__/delete/?_to_field=id&_popup=1" id="delete_id_location" title="Delete selected Location">
|
||||
<img alt="Delete" src="/static/admin/img/icon-deletelink.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="module aligned collapse">
|
||||
<h2>
|
||||
Lent
|
||||
</h2>
|
||||
<div class="form-row field-lent_to">
|
||||
<div>
|
||||
<label for="id_lent_to">
|
||||
Lent to:
|
||||
</label>
|
||||
<input class="vTextField" id="id_lent_to" maxlength="64" name="lent_to" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-lent_from_date field-lent_until_date">
|
||||
<div class="fieldBox field-lent_from_date">
|
||||
<label for="id_lent_from_date">
|
||||
Lent from date:
|
||||
</label>
|
||||
<input class="vDateField" id="id_lent_from_date" name="lent_from_date" size="10" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-lent_until_date">
|
||||
<label class="inline" for="id_lent_until_date">
|
||||
Lent until date:
|
||||
</label>
|
||||
<input class="vDateField" id="id_lent_until_date" name="lent_until_date" size="10" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="module aligned collapse">
|
||||
<h2>
|
||||
Received
|
||||
</h2>
|
||||
<div class="form-row field-received_from field-received_date field-received_price">
|
||||
<div class="fieldBox field-received_from">
|
||||
<label for="id_received_from">
|
||||
Received from:
|
||||
</label>
|
||||
<input class="vTextField" id="id_received_from" maxlength="64" name="received_from" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-received_date">
|
||||
<label class="inline" for="id_received_date">
|
||||
Received date:
|
||||
</label>
|
||||
<input class="vDateField" id="id_received_date" name="received_date" size="10" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-received_price">
|
||||
<label class="inline" for="id_received_price">
|
||||
Received price:
|
||||
</label>
|
||||
<input id="id_received_price" name="received_price" step="0.01" type="number"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="module aligned collapse">
|
||||
<h2>
|
||||
Handed over
|
||||
</h2>
|
||||
<div class="form-row field-handed_over_to field-handed_over_date field-handed_over_price">
|
||||
<div class="fieldBox field-handed_over_to">
|
||||
<label for="id_handed_over_to">
|
||||
Handed over to:
|
||||
</label>
|
||||
<input class="vTextField" id="id_handed_over_to" maxlength="64" name="handed_over_to" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-handed_over_date">
|
||||
<label class="inline" for="id_handed_over_date">
|
||||
Handed over date:
|
||||
</label>
|
||||
<input class="vDateField" id="id_handed_over_date" name="handed_over_date" size="10" type="text"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-handed_over_price">
|
||||
<label class="inline" for="id_handed_over_price">
|
||||
Handed over price:
|
||||
</label>
|
||||
<input id="id_handed_over_price" name="handed_over_price" step="0.01" type="number"/>
|
||||
<div class="help">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="inline-group sortable" id="itemimagemodel_set-group">
|
||||
<div class="tabular inline-related">
|
||||
<input id="id_itemimagemodel_set-TOTAL_FORMS" name="itemimagemodel_set-TOTAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemimagemodel_set-INITIAL_FORMS" name="itemimagemodel_set-INITIAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemimagemodel_set-MIN_NUM_FORMS" name="itemimagemodel_set-MIN_NUM_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemimagemodel_set-MAX_NUM_FORMS" name="itemimagemodel_set-MAX_NUM_FORMS" type="hidden" value="1000"/>
|
||||
<fieldset class="module">
|
||||
<h2>
|
||||
Images
|
||||
</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Sort
|
||||
</th>
|
||||
<th colspan="2">
|
||||
Preview
|
||||
</th>
|
||||
<th class="required">
|
||||
Image
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Name
|
||||
<img alt="(BaseItemAttachmentModel.name.help_text)" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title="BaseItemAttachmentModel.name.help_text" width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Tags
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Delete?
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="form-row row1 empty-form" id="itemimagemodel_set-empty">
|
||||
<td class="drag">
|
||||
</td>
|
||||
<td class="original">
|
||||
<input id="id_itemimagemodel_set-__prefix__-id" name="itemimagemodel_set-__prefix__-id" type="hidden"/>
|
||||
<input id="id_itemimagemodel_set-__prefix__-item" name="itemimagemodel_set-__prefix__-item" type="hidden" value="<removed-UUID>"/>
|
||||
<input id="id_itemimagemodel_set-__prefix__-position" name="itemimagemodel_set-__prefix__-position" type="hidden" value="0"/>
|
||||
</td>
|
||||
<td class="field-preview">
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
<td class="field-image">
|
||||
<input accept="image/*" id="id_itemimagemodel_set-__prefix__-image" name="itemimagemodel_set-__prefix__-image" type="file"/>
|
||||
</td>
|
||||
<td class="field-name">
|
||||
<input class="vTextField" id="id_itemimagemodel_set-__prefix__-name" maxlength="255" name="itemimagemodel_set-__prefix__-name" type="text"/>
|
||||
</td>
|
||||
<td class="field-tags">
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list="[]" data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 10, "space_delimiter": false, "required": false}' data-tagulous="true" data-theme="admin-autocomplete" id="id_itemimagemodel_set-__prefix__-tags" name="itemimagemodel_set-__prefix__-tags" type="text"/>
|
||||
</div>
|
||||
</td>
|
||||
<td class="delete">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<script class="inline-tabular-config" type="application/json">
|
||||
{
|
||||
"prefix": "itemimagemodel_set",
|
||||
"addText": "Add another Image",
|
||||
"deleteText": "Remove"
|
||||
}
|
||||
</script>
|
||||
<div class="default_order_field" default_order_direction="" default_order_field="position">
|
||||
</div>
|
||||
<div class="inline-group sortable" id="itemfilemodel_set-group">
|
||||
<div class="tabular inline-related">
|
||||
<input id="id_itemfilemodel_set-TOTAL_FORMS" name="itemfilemodel_set-TOTAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemfilemodel_set-INITIAL_FORMS" name="itemfilemodel_set-INITIAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemfilemodel_set-MIN_NUM_FORMS" name="itemfilemodel_set-MIN_NUM_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemfilemodel_set-MAX_NUM_FORMS" name="itemfilemodel_set-MAX_NUM_FORMS" type="hidden" value="1000"/>
|
||||
<fieldset class="module">
|
||||
<h2>
|
||||
Files
|
||||
</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Sort
|
||||
</th>
|
||||
<th class="required" colspan="2">
|
||||
File
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Name
|
||||
<img alt="(BaseItemAttachmentModel.name.help_text)" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title="BaseItemAttachmentModel.name.help_text" width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Tags
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10">
|
||||
</img>
|
||||
</th>
|
||||
<th>
|
||||
Delete?
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="form-row row1 empty-form" id="itemfilemodel_set-empty">
|
||||
<td class="drag">
|
||||
</td>
|
||||
<td class="original">
|
||||
<input id="id_itemfilemodel_set-__prefix__-id" name="itemfilemodel_set-__prefix__-id" type="hidden"/>
|
||||
<input id="id_itemfilemodel_set-__prefix__-item" name="itemfilemodel_set-__prefix__-item" type="hidden" value="<removed-UUID>"/>
|
||||
<input id="id_itemfilemodel_set-__prefix__-position" name="itemfilemodel_set-__prefix__-position" type="hidden" value="0"/>
|
||||
</td>
|
||||
<td class="field-file">
|
||||
<input id="id_itemfilemodel_set-__prefix__-file" name="itemfilemodel_set-__prefix__-file" type="file"/>
|
||||
</td>
|
||||
<td class="field-name">
|
||||
<input class="vTextField" id="id_itemfilemodel_set-__prefix__-name" maxlength="255" name="itemfilemodel_set-__prefix__-name" type="text"/>
|
||||
</td>
|
||||
<td class="field-tags">
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list="[]" data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 10, "space_delimiter": false, "required": false}' data-tagulous="true" data-theme="admin-autocomplete" id="id_itemfilemodel_set-__prefix__-tags" name="itemfilemodel_set-__prefix__-tags" type="text"/>
|
||||
</div>
|
||||
</td>
|
||||
<td class="delete">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<script class="inline-tabular-config" type="application/json">
|
||||
{
|
||||
"prefix": "itemfilemodel_set",
|
||||
"addText": "Add another File",
|
||||
"deleteText": "Remove"
|
||||
}
|
||||
</script>
|
||||
<div class="default_order_field" default_order_direction="" default_order_field="position">
|
||||
</div>
|
||||
<div class="inline-group sortable" id="itemlinkmodel_set-group">
|
||||
<div class="tabular inline-related last-related">
|
||||
<input id="id_itemlinkmodel_set-TOTAL_FORMS" name="itemlinkmodel_set-TOTAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemlinkmodel_set-INITIAL_FORMS" name="itemlinkmodel_set-INITIAL_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemlinkmodel_set-MIN_NUM_FORMS" name="itemlinkmodel_set-MIN_NUM_FORMS" type="hidden" value="0"/>
|
||||
<input id="id_itemlinkmodel_set-MAX_NUM_FORMS" name="itemlinkmodel_set-MAX_NUM_FORMS" type="hidden" value="1000"/>
|
||||
<fieldset class="module">
|
||||
<h2>
|
||||
Links
|
||||
</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Sort
|
||||
</th>
|
||||
<th colspan="2">
|
||||
Tags
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10"/>
|
||||
</th>
|
||||
<th>
|
||||
Name
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10"/>
|
||||
</th>
|
||||
<th class="required">
|
||||
URL
|
||||
<img alt="( )" class="help help-tooltip" height="10" src="/static/admin/img/icon-unknown.svg" title=" " width="10"/>
|
||||
</th>
|
||||
<th>
|
||||
Delete?
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="form-row row1 empty-form" id="itemlinkmodel_set-empty">
|
||||
<td class="drag">
|
||||
</td>
|
||||
<td class="original">
|
||||
<input id="id_itemlinkmodel_set-__prefix__-id" name="itemlinkmodel_set-__prefix__-id" type="hidden"/>
|
||||
<input id="id_itemlinkmodel_set-__prefix__-item" name="itemlinkmodel_set-__prefix__-item" type="hidden" value="<removed-UUID>"/>
|
||||
<input id="id_itemlinkmodel_set-__prefix__-position" name="itemlinkmodel_set-__prefix__-position" type="hidden" value="0"/>
|
||||
</td>
|
||||
<td class="field-tags">
|
||||
<div class="related-widget-wrapper">
|
||||
<input autocomplete="off" data-tag-list="[]" data-tag-options='{"case_sensitive": false, "force_lowercase": false, "max_count": 10, "space_delimiter": false, "required": false}' data-tagulous="true" data-theme="admin-autocomplete" id="id_itemlinkmodel_set-__prefix__-tags" name="itemlinkmodel_set-__prefix__-tags" type="text"/>
|
||||
</div>
|
||||
</td>
|
||||
<td class="field-name">
|
||||
<input class="vTextField" id="id_itemlinkmodel_set-__prefix__-name" maxlength="255" name="itemlinkmodel_set-__prefix__-name" type="text"/>
|
||||
</td>
|
||||
<td class="field-url">
|
||||
<input class="vURLField" id="id_itemlinkmodel_set-__prefix__-url" maxlength="200" name="itemlinkmodel_set-__prefix__-url" type="url"/>
|
||||
</td>
|
||||
<td class="delete">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<script class="inline-tabular-config" type="application/json">
|
||||
{
|
||||
"prefix": "itemlinkmodel_set",
|
||||
"addText": "Add another Link",
|
||||
"deleteText": "Remove"
|
||||
}
|
||||
</script>
|
||||
<div class="default_order_field" default_order_direction="" default_order_field="position">
|
||||
</div>
|
||||
<div class="submit-row">
|
||||
<input class="default" name="_save" type="submit" value="Save"/>
|
||||
<p class="deletelink-box">
|
||||
<a class="deletelink" href="/admin/inventory/itemmodel/<removed-UUID>/delete/">
|
||||
Delete
|
||||
</a>
|
||||
</p>
|
||||
<input name="_addanother" type="submit" value="Save and add another"/>
|
||||
<input name="_continue" type="submit" value="Save and continue editing"/>
|
||||
</div>
|
||||
<script async="" id="django-admin-form-add-constants" src="/static/admin/js/change_form.js">
|
||||
</script>
|
||||
<script data-prepopulated-fields="[]" id="django-admin-prepopulated-fields-constants" src="/static/admin/js/prepopulate_init.js">
|
||||
</script>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<br class="clear"/>
|
||||
</div>
|
||||
<!-- END Content -->
|
||||
<div id="footer">
|
||||
<a href="https://github.com/jedie/PyInventory">
|
||||
https://github.com/jedie/PyInventory
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END Container -->
|
||||
</body>
|
||||
</html>
|
|
@ -50,6 +50,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
response = self.client.post(
|
||||
path='/admin/inventory/memomodel/add/',
|
||||
data={
|
||||
'version': 0, # VersionProtectBaseModel field
|
||||
'name': 'The Memo Name',
|
||||
'memo': 'This is a test Memo',
|
||||
|
||||
|
@ -74,6 +75,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
'_save': 'Save',
|
||||
},
|
||||
)
|
||||
assert response.status_code == 302, response.content.decode('utf-8') # Form error?
|
||||
self.assertRedirects(response, expected_url='/admin/inventory/memomodel/')
|
||||
|
||||
data = list(MemoModel.objects.values_list('name', 'memo'))
|
||||
|
@ -99,6 +101,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
response = self.client.post(
|
||||
path='/admin/inventory/memomodel/add/',
|
||||
data={
|
||||
'version': 0, # VersionProtectBaseModel field
|
||||
'name': 'The Memo Name',
|
||||
'memo': 'This is a test Memo',
|
||||
|
||||
|
@ -125,6 +128,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
|||
'_save': 'Save',
|
||||
},
|
||||
)
|
||||
assert response.status_code == 302, response.content.decode('utf-8') # Form error?
|
||||
memo = MemoModel.objects.first() or MemoModel()
|
||||
self.assert_messages(response, expected_messages=[
|
||||
f'The Memo “<a href="/admin/inventory/memomodel/{memo.pk}/change/">The Memo Name</a>”'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>
|
||||
Add Memo | PyInventory v0.11.0
|
||||
Add Memo | PyInventory v0.12.0.rc1
|
||||
</title>
|
||||
<link href="/static/admin/css/base.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/admin/css/nav_sidebar.css" rel="stylesheet" type="text/css"/>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<div id="branding">
|
||||
<h1 id="site-name">
|
||||
<a href="/admin/">
|
||||
PyInventory v0.11.0
|
||||
PyInventory v0.12.0.rc1
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
@ -182,8 +182,8 @@
|
|||
<h2>
|
||||
Internals
|
||||
</h2>
|
||||
<div class="form-row field-id">
|
||||
<div>
|
||||
<div class="form-row field-id field-version">
|
||||
<div class="fieldBox field-id">
|
||||
<label>
|
||||
ID:
|
||||
</label>
|
||||
|
@ -194,6 +194,16 @@
|
|||
ID
|
||||
</div>
|
||||
</div>
|
||||
<div class="fieldBox field-version">
|
||||
<label class="required inline" for="id_version">
|
||||
Version:
|
||||
</label>
|
||||
<input id="id_version" name="version" required="" type="hidden" value="0"/>
|
||||
0
|
||||
<div class="help">
|
||||
Internal version number of this entry. Used to protect the overwriting of an older entry.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row field-user">
|
||||
<div>
|
||||
|
|
Ładowanie…
Reference in New Issue