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.contrib import admin
|
||||
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 import_export.admin import ImportExportMixin
|
||||
from import_export.resources import ModelResource
|
||||
|
||||
from inventory.admin.base import BaseUserAdmin, LimitTreeDepthListFilter
|
||||
from inventory.models import LocationModel
|
||||
from inventory.models import ItemModel, LocationModel
|
||||
from inventory.string_utils import ltruncatechars
|
||||
|
||||
|
||||
|
@ -22,6 +24,16 @@ class LocationModelAdmin(ImportExportMixin, BaseUserAdmin):
|
|||
def item_count(self, obj):
|
||||
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'))
|
||||
def location(self, obj):
|
||||
text = ' › '.join(obj.path)
|
||||
|
@ -34,7 +46,33 @@ class LocationModelAdmin(ImportExportMixin, BaseUserAdmin):
|
|||
return qs
|
||||
|
||||
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_filter = (LimitTreeDepthListFilter,)
|
||||
search_fields = ('name', 'description', 'tags__name')
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \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"
|
||||
"Last-Translator: Jaume López\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -54,9 +54,15 @@ msgstr "Rebuts"
|
|||
msgid "Handed over"
|
||||
msgstr "Donats"
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Elements"
|
||||
|
||||
msgid "LocationModel.verbose_name"
|
||||
msgstr "Localització"
|
||||
|
||||
msgid "Items in this Location"
|
||||
msgstr ""
|
||||
|
||||
msgid "BaseModel.id.verbose_name"
|
||||
msgstr "ID"
|
||||
|
||||
|
@ -180,9 +186,6 @@ msgstr "Preu de cessió"
|
|||
msgid "ItemModel.handed_over_price.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Elements"
|
||||
|
||||
msgid "ItemLinkModel.verbose_name"
|
||||
msgstr "Vincle"
|
||||
|
||||
|
|
Plik binarny nie jest wyświetlany.
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-09-30 20:11+0200\n"
|
||||
"PO-Revision-Date: 2022-09-30 20:10+0200\n"
|
||||
"POT-Creation-Date: 2022-09-30 20:48+0200\n"
|
||||
"PO-Revision-Date: 2022-09-30 20:48+0200\n"
|
||||
"Last-Translator: Jens Diemer\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
|
@ -54,9 +54,15 @@ msgstr "Erhalt"
|
|||
msgid "Handed over"
|
||||
msgstr "Abgabe"
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Gegenstände"
|
||||
|
||||
msgid "LocationModel.verbose_name"
|
||||
msgstr "Standort"
|
||||
|
||||
msgid "Items in this Location"
|
||||
msgstr "Gegenstände an diesem Ort:"
|
||||
|
||||
msgid "BaseModel.id.verbose_name"
|
||||
msgstr "ID"
|
||||
|
||||
|
@ -179,9 +185,6 @@ msgstr "Abgabepreis"
|
|||
msgid "ItemModel.handed_over_price.help_text"
|
||||
msgstr "Wurde bei der Abgabe Geld eingenommen?"
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Gegenstände"
|
||||
|
||||
msgid "ItemLinkModel.verbose_name"
|
||||
msgstr "Link"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \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"
|
||||
"Last-Translator: Jens Diemer\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -54,9 +54,15 @@ msgstr ""
|
|||
msgid "Handed over"
|
||||
msgstr ""
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Items"
|
||||
|
||||
msgid "LocationModel.verbose_name"
|
||||
msgstr "Location"
|
||||
|
||||
msgid "Items in this Location"
|
||||
msgstr ""
|
||||
|
||||
msgid "BaseModel.id.verbose_name"
|
||||
msgstr "ID"
|
||||
|
||||
|
@ -179,9 +185,6 @@ msgstr "Handed over price"
|
|||
msgid "ItemModel.handed_over_price.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Items"
|
||||
|
||||
msgid "ItemLinkModel.verbose_name"
|
||||
msgstr "Link"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \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"
|
||||
"Last-Translator: Jaume López\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -54,9 +54,15 @@ msgstr "Recibidos"
|
|||
msgid "Handed over"
|
||||
msgstr "Cedidos"
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Elementos"
|
||||
|
||||
msgid "LocationModel.verbose_name"
|
||||
msgstr "Localización"
|
||||
|
||||
msgid "Items in this Location"
|
||||
msgstr ""
|
||||
|
||||
msgid "BaseModel.id.verbose_name"
|
||||
msgstr "ID"
|
||||
|
||||
|
@ -180,9 +186,6 @@ msgstr "Precio de cesión"
|
|||
msgid "ItemModel.handed_over_price.help_text"
|
||||
msgstr " "
|
||||
|
||||
msgid "ItemModel.verbose_name_plural"
|
||||
msgstr "Elementos"
|
||||
|
||||
msgid "ItemLinkModel.verbose_name"
|
||||
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