Skip to content

Commit 4234670

Browse files
Adds image attachment list view (#12487)
* adds image attachment list view #11932 * fixed typo * Update netbox/extras/tables/tables.py Co-authored-by: Jeremy Stretch <[email protected]> * Update netbox/extras/forms/filtersets.py Co-authored-by: Jeremy Stretch <[email protected]> * changes as per review * Disable ordering by size (not stored in database) --------- Co-authored-by: Jeremy Stretch <[email protected]>
1 parent 9909213 commit 4234670

File tree

6 files changed

+52
-39
lines changed

6 files changed

+52
-39
lines changed

netbox/extras/forms/filtersets.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from netbox.forms.base import NetBoxModelFilterSetForm
1212
from tenancy.models import Tenant, TenantGroup
1313
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
14-
from utilities.forms.fields import ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField
14+
from utilities.forms.fields import ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField
1515
from utilities.forms.widgets import APISelectMultiple, DateTimePicker
1616
from virtualization.models import Cluster, ClusterGroup, ClusterType
1717
from .mixins import SavedFiltersMixin
@@ -22,6 +22,7 @@
2222
'CustomFieldFilterForm',
2323
'CustomLinkFilterForm',
2424
'ExportTemplateFilterForm',
25+
'ImageAttachmentFilterForm',
2526
'JournalEntryFilterForm',
2627
'LocalConfigContextFilterForm',
2728
'ObjectChangeFilterForm',
@@ -137,6 +138,20 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
137138
)
138139

139140

141+
class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
142+
fieldsets = (
143+
(None, ('q', 'filter_id')),
144+
('Attributes', ('content_type_id', 'name',)),
145+
)
146+
content_type_id = ContentTypeChoiceField(
147+
queryset=ContentType.objects.filter(FeatureQuery('custom_fields').get_query()),
148+
required=False
149+
)
150+
name = forms.CharField(
151+
required=False
152+
)
153+
154+
140155
class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
141156
fieldsets = (
142157
(None, ('q', 'filter_id')),

netbox/extras/tables/tables.py

+23
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
'CustomFieldTable',
1414
'CustomLinkTable',
1515
'ExportTemplateTable',
16+
'ImageAttachmentTable',
1617
'JournalEntryTable',
1718
'ObjectChangeTable',
1819
'SavedFilterTable',
@@ -86,6 +87,28 @@ class Meta(NetBoxTable.Meta):
8687
)
8788

8889

90+
class ImageAttachmentTable(NetBoxTable):
91+
id = tables.Column(
92+
linkify=False
93+
)
94+
content_type = columns.ContentTypeColumn()
95+
parent = tables.Column(
96+
linkify=True
97+
)
98+
size = tables.Column(
99+
orderable=False,
100+
verbose_name='Size (bytes)'
101+
)
102+
103+
class Meta(NetBoxTable.Meta):
104+
model = ImageAttachment
105+
fields = (
106+
'pk', 'content_type', 'parent', 'image', 'name', 'image_height', 'image_width', 'size', 'created',
107+
'last_updated',
108+
)
109+
default_columns = ('content_type', 'parent', 'image', 'name', 'size', 'created')
110+
111+
89112
class SavedFilterTable(NetBoxTable):
90113
name = tables.Column(
91114
linkify=True

netbox/extras/urls.py

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
path('config-templates/<int:pk>/', include(get_model_urls('extras', 'configtemplate'))),
7474

7575
# Image attachments
76+
path('image-attachments/', views.ImageAttachmentListView.as_view(), name='imageattachment_list'),
7677
path('image-attachments/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'),
7778
path('image-attachments/<int:pk>/', include(get_model_urls('extras', 'imageattachment'))),
7879

netbox/extras/views.py

+8
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,14 @@ def get_extra_context(self, request, instance):
577577
# Image attachments
578578
#
579579

580+
class ImageAttachmentListView(generic.ObjectListView):
581+
queryset = ImageAttachment.objects.all()
582+
filterset = filtersets.ImageAttachmentFilterSet
583+
filterset_form = forms.ImageAttachmentFilterForm
584+
table = tables.ImageAttachmentTable
585+
actions = ('export',)
586+
587+
580588
@register_model_view(ImageAttachment, 'edit')
581589
class ImageAttachmentEditView(generic.ObjectEditView):
582590
queryset = ImageAttachment.objects.all()

netbox/netbox/navigation/menu.py

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@
292292
get_model_item('extras', 'exporttemplate', _('Export Templates')),
293293
get_model_item('extras', 'savedfilter', _('Saved Filters')),
294294
get_model_item('extras', 'tag', 'Tags'),
295+
get_model_item('extras', 'imageattachment', _('Image Attachments'), actions=()),
295296
),
296297
),
297298
MenuGroup(

netbox/templates/inc/panels/image_attachments.html

+3-38
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,9 @@
44
<h5 class="card-header">
55
Images
66
</h5>
7-
<div class="card-body">
8-
{% with images=object.images.all %}
9-
{% if images.exists %}
10-
<table class="table table-hover">
11-
<tr>
12-
<th>Name</th>
13-
<th>Size</th>
14-
<th>Created</th>
15-
<th></th>
16-
</tr>
17-
{% for attachment in images %}
18-
<tr{% if not attachment.size %} class="table-danger"{% endif %}>
19-
<td>
20-
<i class="mdi mdi-file-image-outline"></i>
21-
<a class="image-preview" href="{{ attachment.image.url }}" target="_blank">{{ attachment }}</a>
22-
</td>
23-
<td>{{ attachment.size|filesizeformat }}</td>
24-
<td>{{ attachment.created|annotated_date }}</td>
25-
<td class="text-end noprint">
26-
{% if perms.extras.change_imageattachment %}
27-
<a href="{% url 'extras:imageattachment_edit' pk=attachment.pk %}" class="btn btn-warning btn-sm lh-1" title="Edit Image">
28-
<i class="mdi mdi-pencil" aria-hidden="true"></i>
29-
</a>
30-
{% endif %}
31-
{% if perms.extras.delete_imageattachment %}
32-
<a href="{% url 'extras:imageattachment_delete' pk=attachment.pk %}" class="btn btn-danger btn-sm lh-1" title="Delete Image">
33-
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i>
34-
</a>
35-
{% endif %}
36-
</td>
37-
</tr>
38-
{% endfor %}
39-
</table>
40-
{% else %}
41-
<div class="text-muted">None</div>
42-
{% endif %}
43-
{% endwith %}
44-
</div>
7+
<div class="card-body htmx-container table-responsive"
8+
hx-get="{% url 'extras:imageattachment_list' %}?content_type_id={{ object|content_type_id }}&object_id={{ object.pk }}"
9+
hx-trigger="load"></div>
4510
{% if perms.extras.add_imageattachment %}
4611
<div class="card-footer text-end noprint">
4712
<a href="{% url 'extras:imageattachment_add' %}?content_type={{ object|content_type_id }}&object_id={{ object.pk }}" class="btn btn-primary btn-sm">

0 commit comments

Comments
 (0)