Merge pull request #121 from jedie/dev2

NEW: List all related objects on `item` change page with edit links.
pull/122/head
Jens Diemer 2022-09-30 20:33:37 +02:00 zatwierdzone przez GitHub
commit b0c6acc02a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
15 zmienionych plików z 294 dodań i 153 usunięć

Wyświetl plik

@ -155,6 +155,7 @@ Files are separated into: "/src/" and "/development/"
* [**dev**](https://github.com/jedie/PyInventory/compare/0.16.0...main)
* NEW: List all related objects on `item` change page with edit links.
* Change `parent` and `location` fields on `item` change page to a autocompele field.
* Add search to `location`
* tbc

Wyświetl plik

@ -4,6 +4,7 @@ import tagulous
from adminsortable2.admin import SortableInlineAdminMixin
from django.conf import settings
from django.contrib import admin
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
@ -45,6 +46,19 @@ class ItemModelResource(ModelResource):
@admin.register(ItemModel)
class ItemModelAdmin(ImportExportMixin, BaseUserAdmin):
@admin.display(description=_('Related items'))
def related_items(self, obj):
if obj.pk is None:
# Add a new item -> there are no related items ;)
return '-'
related_qs = ItemModel.tree_objects.related_objects(instance=obj)
context = {
'items': related_qs,
'opts': self.opts,
}
return render_to_string('admin/item/related_items.html', context)
@admin.display(ordering='path_str', description=_('ItemModel.verbose_name'))
def item(self, obj):
path = obj.path
@ -78,47 +92,62 @@ class ItemModelAdmin(ImportExportMixin, BaseUserAdmin):
list_filter = (LimitTreeDepthListFilter, 'kind', 'location', 'producer', 'tags')
search_fields = ('name', 'description', 'kind__name', 'tags__name')
fieldsets = (
(_('Internals'), {
'classes': ('collapse',),
'fields': (
('id', 'version'),
'user',
)
}),
(_('Meta'), {
'classes': ('collapse',),
'fields': (
'create_dt', 'update_dt'
)
}),
(_('Basic'), {'fields': (
'kind',
('producer', 'name'),
'description',
'tags',
'fcc_id',
'parent',
'location',
)}),
(_('Lent'), {
'classes': ('collapse',),
'fields': (
'lent_to',
('lent_from_date', 'lent_until_date',)
)}),
(_('Received'), {
'classes': ('collapse',),
'fields': (
('received_from', 'received_date', 'received_price'),
)}),
(_('Handed over'), {
'classes': ('collapse',),
'fields': (
('handed_over_to', 'handed_over_date', 'handed_over_price'),
)}),
(
_('Internals'),
{
'classes': ('collapse',),
'fields': (
('id', 'version'),
'user',
),
},
),
(_('Meta'), {'classes': ('collapse',), 'fields': ('create_dt', 'update_dt')}),
(
_('Basic'),
{
'fields': (
'kind',
('producer', 'name'),
'description',
'tags',
'fcc_id',
'parent',
'location',
)
},
),
(_('Related items'), {'classes': ('collapse',), 'fields': ('related_items',)}),
(
_('Lent'),
{
'classes': ('collapse',),
'fields': (
'lent_to',
(
'lent_from_date',
'lent_until_date',
),
),
},
),
(
_('Received'),
{
'classes': ('collapse',),
'fields': (('received_from', 'received_date', 'received_price'),),
},
),
(
_('Handed over'),
{
'classes': ('collapse',),
'fields': (('handed_over_to', 'handed_over_date', 'handed_over_price'),),
},
),
)
autocomplete_fields = ('parent', 'location')
readonly_fields = ('id', 'create_dt', 'update_dt', 'user')
readonly_fields = ('id', 'create_dt', 'update_dt', 'user', 'related_items')
inlines = (ItemImageModelInline, ItemFileModelInline, ItemLinkModelInline)

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-09 19:36+0200\n"
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
"PO-Revision-Date: 2022-09-30 20:07+0200\n"
"Last-Translator: Jaume López\n"
"Language-Team: \n"
"Language: ca\n"
@ -18,17 +18,23 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
msgid "Group Items"
msgstr "Agrupa"
msgid "Limit tree depth"
msgstr ""
msgid "Automatic"
msgstr "Automàtic"
msgid "Only root"
msgstr ""
msgid "No"
msgstr "No"
msgid "Root + first sub"
msgstr ""
msgid "ItemModel.verbose_name_plural"
msgstr "Elements"
msgid "Root + first + second sub"
msgstr ""
msgid "Related items"
msgstr ""
msgid "ItemModel.verbose_name"
msgstr "Element"
msgid "Internals"
msgstr "Interns"
@ -48,6 +54,9 @@ msgstr "Rebuts"
msgid "Handed over"
msgstr "Donats"
msgid "LocationModel.verbose_name"
msgstr "Localització"
msgid "BaseModel.id.verbose_name"
msgstr "ID"
@ -59,8 +68,8 @@ msgstr "Usuari"
msgid "BaseModel.user.help_text"
msgstr ""
"L'usuari propietari d'aquesta entrada i pugui gestionar-la"
"(s'assignarà automàticament)"
"L'usuari propietari d'aquesta entrada i pugui gestionar-la(s'assignarà "
"automàticament)"
msgid "BaseModel.name.verbose_name"
msgstr "Nom"
@ -74,6 +83,13 @@ msgstr "Etiquetes"
msgid "BaseModel.tags.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Parent"
msgid "LocationModel.parent.help_text"
msgstr ""
"Las ubicaciones pueden estar anidadas. Ejemplo: La caja 12 en el armario 3"
msgid "BaseItemAttachmentModel.name.verbose_name"
msgstr "Nom"
@ -110,12 +126,6 @@ msgstr "Localització"
msgid "ItemModel.location.help_text"
msgstr " "
msgid "ItemModel.parent.verbose_name"
msgstr "parent"
msgid "ItemModel.parent.help_text"
msgstr " "
msgid "ItemModel.lent_to.verbose_name"
msgstr "Deixat"
@ -170,8 +180,8 @@ msgstr "Preu de cessió"
msgid "ItemModel.handed_over_price.help_text"
msgstr " "
msgid "ItemModel.verbose_name"
msgstr "Element"
msgid "ItemModel.verbose_name_plural"
msgstr "Elements"
msgid "ItemLinkModel.verbose_name"
msgstr "Vincle"
@ -233,17 +243,6 @@ msgstr "Descripció"
msgid "LocationModel.description.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Parent"
msgid "LocationModel.parent.help_text"
msgstr "Locations can be nested. Example: The box 12 in cupboard 3"
msgstr "Les localitzacions poden ser sumades."
"Exemple: La caixa 12 a l'estant 3"
msgid "LocationModel.verbose_name"
msgstr "Localització"
msgid "LocationModel.verbose_name_plural"
msgstr "Localitzacions"
@ -288,3 +287,8 @@ msgstr "Arxiu"
msgid "MemoFileModel.verbose_name_plural"
msgstr "Arxius"
#, fuzzy
#| msgid "No"
msgid "No."
msgstr "No"

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-09 19:36+0200\n"
"PO-Revision-Date: 2021-10-09 19:35+0200\n"
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
"PO-Revision-Date: 2022-09-30 20:10+0200\n"
"Last-Translator: Jens Diemer\n"
"Language-Team: \n"
"Language: de\n"
@ -18,17 +18,23 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
msgid "Group Items"
msgstr "Gegenstände Gruppieren"
msgid "Limit tree depth"
msgstr "Tiefe des Baumes"
msgid "Automatic"
msgstr "Automatisch"
msgid "Only root"
msgstr "Nur Stamm"
msgid "No"
msgstr ""
msgid "Root + first sub"
msgstr "Stamm + erste Untergruppe"
msgid "ItemModel.verbose_name_plural"
msgstr "Gegenstände"
msgid "Root + first + second sub"
msgstr "Stamm + erste + zweite Untergruppe"
msgid "Related items"
msgstr "Zugehörige Gegenstände"
msgid "ItemModel.verbose_name"
msgstr "Gegenstand"
msgid "Internals"
msgstr "Intern"
@ -37,7 +43,7 @@ msgid "Meta"
msgstr ""
msgid "Basic"
msgstr ""
msgstr "Basis"
msgid "Lent"
msgstr "Verleih"
@ -48,6 +54,9 @@ msgstr "Erhalt"
msgid "Handed over"
msgstr "Abgabe"
msgid "LocationModel.verbose_name"
msgstr "Standort"
msgid "BaseModel.id.verbose_name"
msgstr "ID"
@ -74,6 +83,12 @@ msgstr "Tags"
msgid "BaseModel.tags.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Übergeordneter Standort"
msgid "LocationModel.parent.help_text"
msgstr "Standorte können verschachtelt werden. Bsp: Der Karton 12 in Schrank 3"
msgid "BaseItemAttachmentModel.name.verbose_name"
msgstr "Name"
@ -110,14 +125,6 @@ msgstr "Standort"
msgid "ItemModel.location.help_text"
msgstr "Wo ist dieser Gegenstand eingelagert?"
msgid "ItemModel.parent.verbose_name"
msgstr "Übergeordnet"
msgid "ItemModel.parent.help_text"
msgstr ""
"Eingebaut in einem anderen Gegenstand? (e.g.: Grafikkarte eingebaut in "
"Rechner)"
msgid "ItemModel.lent_to.verbose_name"
msgstr "Verliehen an"
@ -172,8 +179,8 @@ msgstr "Abgabepreis"
msgid "ItemModel.handed_over_price.help_text"
msgstr "Wurde bei der Abgabe Geld eingenommen?"
msgid "ItemModel.verbose_name"
msgstr "Gegenstand"
msgid "ItemModel.verbose_name_plural"
msgstr "Gegenstände"
msgid "ItemLinkModel.verbose_name"
msgstr "Link"
@ -235,15 +242,6 @@ msgstr "Beschreibung"
msgid "LocationModel.description.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Übergeordneter Standort"
msgid "LocationModel.parent.help_text"
msgstr "Standorte können verschachtelt werden. Bsp: Der Karton 12 in Schrank 3"
msgid "LocationModel.verbose_name"
msgstr "Standort"
msgid "LocationModel.verbose_name_plural"
msgstr "Standorte"
@ -288,3 +286,6 @@ msgstr "Datei"
msgid "MemoFileModel.verbose_name_plural"
msgstr "Dateien"
msgid "No."
msgstr "Nr."

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-09 19:36+0200\n"
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
"Last-Translator: Jens Diemer\n"
"Language-Team: \n"
@ -18,17 +18,23 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
msgid "Group Items"
msgid "Limit tree depth"
msgstr ""
msgid "Automatic"
msgid "Only root"
msgstr ""
msgid "No"
msgid "Root + first sub"
msgstr ""
msgid "ItemModel.verbose_name_plural"
msgstr "Items"
msgid "Root + first + second sub"
msgstr ""
msgid "Related items"
msgstr ""
msgid "ItemModel.verbose_name"
msgstr "Item"
msgid "Internals"
msgstr ""
@ -48,6 +54,9 @@ msgstr ""
msgid "Handed over"
msgstr ""
msgid "LocationModel.verbose_name"
msgstr "Location"
msgid "BaseModel.id.verbose_name"
msgstr "ID"
@ -74,6 +83,12 @@ msgstr "Tags"
msgid "BaseModel.tags.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Parent"
msgid "LocationModel.parent.help_text"
msgstr "Locations can be nested. Example: The box 12 in cupboard 3"
msgid "BaseItemAttachmentModel.name.verbose_name"
msgstr "Name"
@ -110,12 +125,6 @@ msgstr "Location"
msgid "ItemModel.location.help_text"
msgstr " "
msgid "ItemModel.parent.verbose_name"
msgstr "parent"
msgid "ItemModel.parent.help_text"
msgstr " "
msgid "ItemModel.lent_to.verbose_name"
msgstr "Lent to"
@ -170,8 +179,8 @@ msgstr "Handed over price"
msgid "ItemModel.handed_over_price.help_text"
msgstr " "
msgid "ItemModel.verbose_name"
msgstr "Item"
msgid "ItemModel.verbose_name_plural"
msgstr "Items"
msgid "ItemLinkModel.verbose_name"
msgstr "Link"
@ -233,15 +242,6 @@ msgstr "Description"
msgid "LocationModel.description.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Parent"
msgid "LocationModel.parent.help_text"
msgstr "Locations can be nested. Example: The box 12 in cupboard 3"
msgid "LocationModel.verbose_name"
msgstr "Location"
msgid "LocationModel.verbose_name_plural"
msgstr "Locations"
@ -286,3 +286,6 @@ msgstr "File"
msgid "MemoFileModel.verbose_name_plural"
msgstr "Files"
msgid "No."
msgstr ""

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-09 19:36+0200\n"
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
"Last-Translator: Jaume López\n"
"Language-Team: \n"
@ -18,17 +18,23 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
msgid "Group Items"
msgstr "Agrupa"
msgid "Limit tree depth"
msgstr ""
msgid "Automatic"
msgstr "Automático"
msgid "Only root"
msgstr ""
msgid "No"
msgstr "No"
msgid "Root + first sub"
msgstr ""
msgid "ItemModel.verbose_name_plural"
msgstr "Elementos"
msgid "Root + first + second sub"
msgstr ""
msgid "Related items"
msgstr ""
msgid "ItemModel.verbose_name"
msgstr "Elemento"
msgid "Internals"
msgstr "Internos"
@ -48,6 +54,9 @@ msgstr "Recibidos"
msgid "Handed over"
msgstr "Cedidos"
msgid "LocationModel.verbose_name"
msgstr "Localización"
msgid "BaseModel.id.verbose_name"
msgstr "ID"
@ -59,8 +68,8 @@ msgstr "Usuario"
msgid "BaseModel.user.help_text"
msgstr ""
"El usuario propietario de esta entrada y pueda gestionarla"
"(se asignará automáticamente)"
"El usuario propietario de esta entrada y pueda gestionarla(se asignará "
"automáticamente)"
msgid "BaseModel.name.verbose_name"
msgstr "Nombre"
@ -74,6 +83,13 @@ msgstr "Etiquetas"
msgid "BaseModel.tags.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Pariente"
msgid "LocationModel.parent.help_text"
msgstr ""
"Las localizaciones pueden ser sumadas.Exemple: La caja 12 del estante 3"
msgid "BaseItemAttachmentModel.name.verbose_name"
msgstr "Nombre"
@ -110,12 +126,6 @@ msgstr "Localización"
msgid "ItemModel.location.help_text"
msgstr " "
msgid "ItemModel.parent.verbose_name"
msgstr "pariente"
msgid "ItemModel.parent.help_text"
msgstr " "
msgid "ItemModel.lent_to.verbose_name"
msgstr "Dejado"
@ -170,8 +180,8 @@ msgstr "Precio de cesión"
msgid "ItemModel.handed_over_price.help_text"
msgstr " "
msgid "ItemModel.verbose_name"
msgstr "Elemento"
msgid "ItemModel.verbose_name_plural"
msgstr "Elementos"
msgid "ItemLinkModel.verbose_name"
msgstr "Vínculo"
@ -233,16 +243,6 @@ msgstr "Descripción"
msgid "LocationModel.description.help_text"
msgstr " "
msgid "LocationModel.parent.verbose_name"
msgstr "Pariente"
msgid "LocationModel.parent.help_text"
msgstr "Las localizaciones pueden ser sumadas."
"Exemple: La caja 12 del estante 3"
msgid "LocationModel.verbose_name"
msgstr "Localización"
msgid "LocationModel.verbose_name_plural"
msgstr "Localitzaciones"
@ -287,3 +287,8 @@ msgstr "Archivo"
msgid "MemoFileModel.verbose_name_plural"
msgstr "Archivos"
#, fuzzy
#| msgid "No"
msgid "No."
msgstr "No"

Wyświetl plik

@ -8,6 +8,7 @@ import tagulous.models
from bx_django_utils.models.timetracking import TimetrackingBaseModel
from django.conf import settings
from django.db import models
from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
from inventory.parent_tree import ValuesListTree
@ -78,7 +79,7 @@ def generate_path_str(path):
class ParentTreeModelManager(models.Manager):
def update_tree_info(self):
def update_tree_info(self) -> None:
start_time = time.monotonic()
values = self.all().values('pk', 'name', 'parent__pk', 'path')
@ -107,6 +108,20 @@ class ParentTreeModelManager(models.Manager):
duration = (time.monotonic() - start_time) * 1000
logger.info('Update %i entries in %ims', len(entries), duration)
def related_objects(self, instance: 'BaseParentTreeModel') -> QuerySet:
"""
Returns a QuerySet with relation section of the tree
"""
path = instance.path
if path is None:
# Not saved -> Can't have related objects ;)
return self.none()
root_entry = path[0]
qs = self.all()
qs = qs.filter(path__0=root_entry)
return qs
class BaseParentTreeModel(BaseModel):
path = models.JSONField(

Wyświetl plik

@ -0,0 +1,18 @@
{% load i18n admin_urls %}
<table>
<thead>
<tr>
<th>{% trans "No." %}</th>
<th>{% trans "ItemModel.verbose_name_plural" %}</th>
</tr>
</thead>
<tbody>
{% for obj in items %}
<tr>
<td>{{ forloop.counter }}</td>
<td><a href="{% url opts|admin_urlname:'change' obj.pk %}">{{ obj }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>

Wyświetl plik

@ -1,4 +1,5 @@
from bx_django_utils.test_utils.assert_queries import AssertQueries
from django.db.models import QuerySet
from django.test import TestCase
from inventory.admin import ItemModelAdmin, LocationModelAdmin
@ -54,6 +55,11 @@ class TreeModelTests(TestCase):
]
item_2_1 = ItemModel.objects.get(name='2.1.')
related_qs = ItemModel.tree_objects.related_objects(instance=item_2_1)
data = list(related_qs.values_list('name', flat=True))
assert data == ['2.', '2.1.', '2.1.1.', '2.1.2.', '2.2.', '2.2.1.', '2.2.2.']
item_2_1.name = 'NEW 2.1. Name'
with AssertQueries() as queries:
item_2_1.save()
@ -93,6 +99,12 @@ class TreeModelTests(TestCase):
similar=True,
)
def test_related_objects(self):
item = ItemModel()
qs = ItemModel.tree_objects.related_objects(instance=item)
assert isinstance(qs, QuerySet)
assert qs.query.is_empty() is True
def test_parent_tree_model_ordering(self):
assert LocationModel._meta.ordering == ('path_str',)
assert LocationModelAdmin.ordering == ('path_str',)

Wyświetl plik

@ -200,6 +200,21 @@
</div>
</div>
</fieldset>
<fieldset class="module aligned collapse">
<h2>
Related items
</h2>
<div class="form-row field-related_items">
<div>
<label>
Related items:
</label>
<div class="readonly">
-
</div>
</div>
</div>
</fieldset>
<fieldset class="module aligned collapse">
<h2>
Lent

Wyświetl plik

@ -411,6 +411,44 @@
</div>
</div>
</fieldset>
<fieldset class="module aligned collapse">
<h2>
Related items
</h2>
<div class="form-row field-related_items">
<div>
<label>
Related items:
</label>
<div class="readonly">
<table>
<thead>
<tr>
<th>
No.
</th>
<th>
Items
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
1
</td>
<td>
<a href="/admin/inventory/itemmodel/&lt;removed-UUID&gt;/change/">
name
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</fieldset>
<fieldset class="module aligned collapse">
<h2>
Lent