kopia lustrzana https://github.com/jedie/PyInventory
Enhance Location: Better change form and list all items in this location
rodzic
3850f9b8a6
commit
c1a690b2fa
|
@ -1,12 +1,14 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
|
from django.db.models.options import Options
|
||||||
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from import_export.admin import ImportExportMixin
|
from import_export.admin import ImportExportMixin
|
||||||
from import_export.resources import ModelResource
|
from import_export.resources import ModelResource
|
||||||
|
|
||||||
from inventory.admin.base import BaseUserAdmin, LimitTreeDepthListFilter
|
from inventory.admin.base import BaseUserAdmin, LimitTreeDepthListFilter
|
||||||
from inventory.models import LocationModel
|
from inventory.models import ItemModel, LocationModel
|
||||||
from inventory.string_utils import ltruncatechars
|
from inventory.string_utils import ltruncatechars
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +24,16 @@ class LocationModelAdmin(ImportExportMixin, BaseUserAdmin):
|
||||||
def item_count(self, obj):
|
def item_count(self, obj):
|
||||||
return obj.item_count
|
return obj.item_count
|
||||||
|
|
||||||
|
@admin.display(description=_('ItemModel.verbose_name_plural'))
|
||||||
|
def items(self, obj):
|
||||||
|
item_qs = ItemModel.objects.filter(location=obj)
|
||||||
|
opts: Options = ItemModel._meta
|
||||||
|
context = {
|
||||||
|
'items': item_qs,
|
||||||
|
'opts': opts,
|
||||||
|
}
|
||||||
|
return render_to_string('admin/location/items.html', context)
|
||||||
|
|
||||||
@admin.display(ordering='path_str', description=_('LocationModel.verbose_name'))
|
@admin.display(ordering='path_str', description=_('LocationModel.verbose_name'))
|
||||||
def location(self, obj):
|
def location(self, obj):
|
||||||
text = ' › '.join(obj.path)
|
text = ' › '.join(obj.path)
|
||||||
|
@ -34,7 +46,33 @@ class LocationModelAdmin(ImportExportMixin, BaseUserAdmin):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
list_display = ('location', 'create_dt', 'update_dt', 'item_count')
|
list_display = ('location', 'create_dt', 'update_dt', 'item_count')
|
||||||
readonly_fields = ('item_count',)
|
fieldsets = (
|
||||||
|
(
|
||||||
|
_('Internals'),
|
||||||
|
{
|
||||||
|
'classes': ('collapse',),
|
||||||
|
'fields': (
|
||||||
|
('id', 'version'),
|
||||||
|
'user',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(_('Meta'), {'classes': ('collapse',), 'fields': ('create_dt', 'update_dt')}),
|
||||||
|
(
|
||||||
|
_('Basic'),
|
||||||
|
{
|
||||||
|
'fields': (
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
'tags',
|
||||||
|
'parent',
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(_('Items in this Location'), {'fields': ('items',)}),
|
||||||
|
)
|
||||||
|
autocomplete_fields = ('parent',)
|
||||||
|
readonly_fields = ('id', 'create_dt', 'update_dt', 'user', 'item_count', 'items')
|
||||||
list_display_links = ('location',)
|
list_display_links = ('location',)
|
||||||
list_filter = (LimitTreeDepthListFilter,)
|
list_filter = (LimitTreeDepthListFilter,)
|
||||||
search_fields = ('name', 'description', 'tags__name')
|
search_fields = ('name', 'description', 'tags__name')
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
|
"POT-Creation-Date: 2022-09-30 20:48+0200\n"
|
||||||
"PO-Revision-Date: 2022-09-30 20:07+0200\n"
|
"PO-Revision-Date: 2022-09-30 20:07+0200\n"
|
||||||
"Last-Translator: Jaume López\n"
|
"Last-Translator: Jaume López\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@ -54,9 +54,15 @@ msgstr "Rebuts"
|
||||||
msgid "Handed over"
|
msgid "Handed over"
|
||||||
msgstr "Donats"
|
msgstr "Donats"
|
||||||
|
|
||||||
|
msgid "ItemModel.verbose_name_plural"
|
||||||
|
msgstr "Elements"
|
||||||
|
|
||||||
msgid "LocationModel.verbose_name"
|
msgid "LocationModel.verbose_name"
|
||||||
msgstr "Localització"
|
msgstr "Localització"
|
||||||
|
|
||||||
|
msgid "Items in this Location"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BaseModel.id.verbose_name"
|
msgid "BaseModel.id.verbose_name"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
|
@ -180,9 +186,6 @@ msgstr "Preu de cessió"
|
||||||
msgid "ItemModel.handed_over_price.help_text"
|
msgid "ItemModel.handed_over_price.help_text"
|
||||||
msgstr " "
|
msgstr " "
|
||||||
|
|
||||||
msgid "ItemModel.verbose_name_plural"
|
|
||||||
msgstr "Elements"
|
|
||||||
|
|
||||||
msgid "ItemLinkModel.verbose_name"
|
msgid "ItemLinkModel.verbose_name"
|
||||||
msgstr "Vincle"
|
msgstr "Vincle"
|
||||||
|
|
||||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -7,8 +7,8 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
|
"POT-Creation-Date: 2022-09-30 20:48+0200\n"
|
||||||
"PO-Revision-Date: 2022-09-30 20:10+0200\n"
|
"PO-Revision-Date: 2022-09-30 20:48+0200\n"
|
||||||
"Last-Translator: Jens Diemer\n"
|
"Last-Translator: Jens Diemer\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
|
@ -54,9 +54,15 @@ msgstr "Erhalt"
|
||||||
msgid "Handed over"
|
msgid "Handed over"
|
||||||
msgstr "Abgabe"
|
msgstr "Abgabe"
|
||||||
|
|
||||||
|
msgid "ItemModel.verbose_name_plural"
|
||||||
|
msgstr "Gegenstände"
|
||||||
|
|
||||||
msgid "LocationModel.verbose_name"
|
msgid "LocationModel.verbose_name"
|
||||||
msgstr "Standort"
|
msgstr "Standort"
|
||||||
|
|
||||||
|
msgid "Items in this Location"
|
||||||
|
msgstr "Gegenstände an diesem Ort:"
|
||||||
|
|
||||||
msgid "BaseModel.id.verbose_name"
|
msgid "BaseModel.id.verbose_name"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
|
@ -179,9 +185,6 @@ msgstr "Abgabepreis"
|
||||||
msgid "ItemModel.handed_over_price.help_text"
|
msgid "ItemModel.handed_over_price.help_text"
|
||||||
msgstr "Wurde bei der Abgabe Geld eingenommen?"
|
msgstr "Wurde bei der Abgabe Geld eingenommen?"
|
||||||
|
|
||||||
msgid "ItemModel.verbose_name_plural"
|
|
||||||
msgstr "Gegenstände"
|
|
||||||
|
|
||||||
msgid "ItemLinkModel.verbose_name"
|
msgid "ItemLinkModel.verbose_name"
|
||||||
msgstr "Link"
|
msgstr "Link"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
|
"POT-Creation-Date: 2022-09-30 20:48+0200\n"
|
||||||
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
|
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
|
||||||
"Last-Translator: Jens Diemer\n"
|
"Last-Translator: Jens Diemer\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@ -54,9 +54,15 @@ msgstr ""
|
||||||
msgid "Handed over"
|
msgid "Handed over"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "ItemModel.verbose_name_plural"
|
||||||
|
msgstr "Items"
|
||||||
|
|
||||||
msgid "LocationModel.verbose_name"
|
msgid "LocationModel.verbose_name"
|
||||||
msgstr "Location"
|
msgstr "Location"
|
||||||
|
|
||||||
|
msgid "Items in this Location"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BaseModel.id.verbose_name"
|
msgid "BaseModel.id.verbose_name"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
|
@ -179,9 +185,6 @@ msgstr "Handed over price"
|
||||||
msgid "ItemModel.handed_over_price.help_text"
|
msgid "ItemModel.handed_over_price.help_text"
|
||||||
msgstr " "
|
msgstr " "
|
||||||
|
|
||||||
msgid "ItemModel.verbose_name_plural"
|
|
||||||
msgstr "Items"
|
|
||||||
|
|
||||||
msgid "ItemLinkModel.verbose_name"
|
msgid "ItemLinkModel.verbose_name"
|
||||||
msgstr "Link"
|
msgstr "Link"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
|
"POT-Creation-Date: 2022-09-30 20:48+0200\n"
|
||||||
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
|
"PO-Revision-Date: 2021-10-09 19:36+0200\n"
|
||||||
"Last-Translator: Jaume López\n"
|
"Last-Translator: Jaume López\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@ -54,9 +54,15 @@ msgstr "Recibidos"
|
||||||
msgid "Handed over"
|
msgid "Handed over"
|
||||||
msgstr "Cedidos"
|
msgstr "Cedidos"
|
||||||
|
|
||||||
|
msgid "ItemModel.verbose_name_plural"
|
||||||
|
msgstr "Elementos"
|
||||||
|
|
||||||
msgid "LocationModel.verbose_name"
|
msgid "LocationModel.verbose_name"
|
||||||
msgstr "Localización"
|
msgstr "Localización"
|
||||||
|
|
||||||
|
msgid "Items in this Location"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BaseModel.id.verbose_name"
|
msgid "BaseModel.id.verbose_name"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
|
@ -180,9 +186,6 @@ msgstr "Precio de cesión"
|
||||||
msgid "ItemModel.handed_over_price.help_text"
|
msgid "ItemModel.handed_over_price.help_text"
|
||||||
msgstr " "
|
msgstr " "
|
||||||
|
|
||||||
msgid "ItemModel.verbose_name_plural"
|
|
||||||
msgstr "Elementos"
|
|
||||||
|
|
||||||
msgid "ItemLinkModel.verbose_name"
|
msgid "ItemLinkModel.verbose_name"
|
||||||
msgstr "Vínculo"
|
msgstr "Vínculo"
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -0,0 +1,37 @@
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from bx_django_utils.test_utils.html_assertion import (
|
||||||
|
HtmlAssertionMixin,
|
||||||
|
assert_html_response_snapshot,
|
||||||
|
)
|
||||||
|
from django.template.defaulttags import CsrfTokenNode, NowNode
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
from inventory import __version__
|
||||||
|
from inventory_project.tests.fixtures import get_normal_user
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(SECURE_SSL_REDIRECT=False)
|
||||||
|
class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.normaluser = get_normal_user()
|
||||||
|
|
||||||
|
def test_empty_change_list(self):
|
||||||
|
self.client.force_login(self.normaluser)
|
||||||
|
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
||||||
|
CsrfTokenNode, 'render', return_value='MockedCsrfTokenNode'
|
||||||
|
):
|
||||||
|
response = self.client.get(
|
||||||
|
path='/admin/inventory/locationmodel/',
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
self.assert_html_parts(
|
||||||
|
response,
|
||||||
|
parts=(
|
||||||
|
f'<title>Select Location to change | PyInventory v{__version__}</title>',
|
||||||
|
'<a href="/admin/inventory/locationmodel/add/" class="addlink">Add Location</a>',
|
||||||
|
'<p class="paginator">0 Locations</p>',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assert_html_response_snapshot(response=response, validate=False)
|
|
@ -0,0 +1,77 @@
|
||||||
|
<div class="" id="content">
|
||||||
|
<h1>
|
||||||
|
Select Location to change
|
||||||
|
</h1>
|
||||||
|
<div id="content-main">
|
||||||
|
<ul class="object-tools">
|
||||||
|
<li>
|
||||||
|
<a class="import_link" href="/admin/inventory/locationmodel/import/">
|
||||||
|
Import
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="export_link" href="/admin/inventory/locationmodel/export/?">
|
||||||
|
Export
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="addlink" href="/admin/inventory/locationmodel/add/">
|
||||||
|
Add Location
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="module filtered" id="changelist">
|
||||||
|
<div class="changelist-form-container">
|
||||||
|
<div id="toolbar">
|
||||||
|
<form id="changelist-search" method="get">
|
||||||
|
<div>
|
||||||
|
<!-- DIV needed for valid HTML -->
|
||||||
|
<label for="searchbar">
|
||||||
|
<img alt="Search" src="/static/admin/img/search.svg"/>
|
||||||
|
</label>
|
||||||
|
<input autofocus="" id="searchbar" name="q" size="40" type="text" value=""/>
|
||||||
|
<input type="submit" value="Search"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<form id="changelist-form" method="post" novalidate="">
|
||||||
|
MockedCsrfTokenNode
|
||||||
|
<p class="paginator">
|
||||||
|
0 Locations
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="changelist-filter">
|
||||||
|
<h2>
|
||||||
|
Filter
|
||||||
|
</h2>
|
||||||
|
<h3>
|
||||||
|
By Limit tree depth
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="selected">
|
||||||
|
<a href="?" title="All">
|
||||||
|
All
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?level=1" title="Only root">
|
||||||
|
Only root
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?level=2" title="Root + first sub">
|
||||||
|
Root + first sub
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="?level=3" title="Root + first + second sub">
|
||||||
|
Root + first + second sub
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br class="clear"/>
|
||||||
|
</div>
|
Ładowanie…
Reference in New Issue