mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Introduce ObjectAttribute for displaying read-only instance attributes on forms
This commit is contained in:
@ -17,6 +17,7 @@ from utilities.forms.fields import (
|
|||||||
CommentField, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField,
|
CommentField, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField,
|
||||||
DynamicModelMultipleChoiceField, JSONField, SlugField,
|
DynamicModelMultipleChoiceField, JSONField, SlugField,
|
||||||
)
|
)
|
||||||
|
from utilities.forms.rendering import ObjectAttribute
|
||||||
from utilities.forms.widgets import ChoicesWidget, HTMXSelect
|
from utilities.forms.widgets import ChoicesWidget, HTMXSelect
|
||||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||||
|
|
||||||
@ -526,6 +527,9 @@ class ConfigTemplateForm(SyncedDataMixin, forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class ImageAttachmentForm(forms.ModelForm):
|
class ImageAttachmentForm(forms.ModelForm):
|
||||||
|
fieldsets = (
|
||||||
|
(None, (ObjectAttribute('parent'), 'name', 'image')),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ImageAttachment
|
model = ImageAttachment
|
||||||
|
@ -759,7 +759,6 @@ class ImageAttachmentListView(generic.ObjectListView):
|
|||||||
class ImageAttachmentEditView(generic.ObjectEditView):
|
class ImageAttachmentEditView(generic.ObjectEditView):
|
||||||
queryset = ImageAttachment.objects.all()
|
queryset = ImageAttachment.objects.all()
|
||||||
form = forms.ImageAttachmentForm
|
form = forms.ImageAttachmentForm
|
||||||
template_name = 'extras/imageattachment_edit.html'
|
|
||||||
|
|
||||||
def alter_object(self, instance, request, args, kwargs):
|
def alter_object(self, instance, request, args, kwargs):
|
||||||
if not instance.pk:
|
if not instance.pk:
|
||||||
|
@ -16,6 +16,7 @@ from utilities.forms.fields import (
|
|||||||
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
|
||||||
SlugField,
|
SlugField,
|
||||||
)
|
)
|
||||||
|
from utilities.forms.rendering import ObjectAttribute
|
||||||
from utilities.forms.widgets import DatePicker
|
from utilities.forms.widgets import DatePicker
|
||||||
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
|
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
|
||||||
|
|
||||||
@ -502,6 +503,10 @@ class FHRPGroupAssignmentForm(forms.ModelForm):
|
|||||||
queryset=FHRPGroup.objects.all()
|
queryset=FHRPGroup.objects.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fieldsets = (
|
||||||
|
(None, (ObjectAttribute('interface'), 'group', 'priority')),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FHRPGroupAssignment
|
model = FHRPGroupAssignment
|
||||||
fields = ('group', 'priority')
|
fields = ('group', 'priority')
|
||||||
|
@ -1059,7 +1059,6 @@ class FHRPGroupBulkDeleteView(generic.BulkDeleteView):
|
|||||||
class FHRPGroupAssignmentEditView(generic.ObjectEditView):
|
class FHRPGroupAssignmentEditView(generic.ObjectEditView):
|
||||||
queryset = FHRPGroupAssignment.objects.all()
|
queryset = FHRPGroupAssignment.objects.all()
|
||||||
form = forms.FHRPGroupAssignmentForm
|
form = forms.FHRPGroupAssignmentForm
|
||||||
template_name = 'ipam/fhrpgroupassignment_edit.html'
|
|
||||||
|
|
||||||
def alter_object(self, instance, request, args, kwargs):
|
def alter_object(self, instance, request, args, kwargs):
|
||||||
if not instance.pk:
|
if not instance.pk:
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
<div class="field-group mb-5">
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end required">
|
|
||||||
{{ object.parent|meta:"verbose_name"|bettertitle }}
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="form-control-plaintext">
|
|
||||||
{{ object.parent|linkify }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% render_form form %}
|
|
||||||
</div>
|
|
||||||
{% endblock form %}
|
|
@ -1,19 +0,0 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row">
|
|
||||||
<h5 class="col-9 offset-3">{% trans "FHRP Group Assignment" %}</h5>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">{% trans "Interface" %}</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ form.instance.interface }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% render_field form.group %}
|
|
||||||
{% render_field form.priority %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,35 +0,0 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block form %}
|
|
||||||
{% for field in form.hidden_fields %}
|
|
||||||
{{ field }}
|
|
||||||
{% endfor %}
|
|
||||||
<div class="field-group my-5">
|
|
||||||
<div class="row">
|
|
||||||
<h5 class="col-9 offset-3">{% trans "Contact Assignment" %}</h5>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">
|
|
||||||
{{ form.instance.object|meta:'verbose_name'|bettertitle }}
|
|
||||||
</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ form.instance.object }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% render_field form.group %}
|
|
||||||
{% render_field form.contact %}
|
|
||||||
{% render_field form.role %}
|
|
||||||
{% render_field form.priority %}
|
|
||||||
{% render_field form.tags %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-group mb-5">
|
|
||||||
<div class="row">
|
|
||||||
<h5 class="col-9 offset-3">{% trans "Custom Fields" %}</h5>
|
|
||||||
</div>
|
|
||||||
{% render_custom_fields form %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from netbox.forms import NetBoxModelForm
|
from netbox.forms import NetBoxModelForm
|
||||||
from tenancy.models import *
|
from tenancy.models import *
|
||||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField
|
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField
|
||||||
|
from utilities.forms.rendering import ObjectAttribute
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ContactAssignmentForm',
|
'ContactAssignmentForm',
|
||||||
@ -140,6 +141,10 @@ class ContactAssignmentForm(NetBoxModelForm):
|
|||||||
queryset=ContactRole.objects.all()
|
queryset=ContactRole.objects.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fieldsets = (
|
||||||
|
(None, (ObjectAttribute('object'), 'group', 'contact', 'role', 'priority', 'tags')),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ContactAssignment
|
model = ContactAssignment
|
||||||
fields = (
|
fields = (
|
||||||
|
@ -369,7 +369,6 @@ class ContactAssignmentListView(generic.ObjectListView):
|
|||||||
class ContactAssignmentEditView(generic.ObjectEditView):
|
class ContactAssignmentEditView(generic.ObjectEditView):
|
||||||
queryset = ContactAssignment.objects.all()
|
queryset = ContactAssignment.objects.all()
|
||||||
form = forms.ContactAssignmentForm
|
form = forms.ContactAssignmentForm
|
||||||
template_name = 'tenancy/contactassignment_edit.html'
|
|
||||||
|
|
||||||
def alter_object(self, instance, request, args, kwargs):
|
def alter_object(self, instance, request, args, kwargs):
|
||||||
if not instance.pk:
|
if not instance.pk:
|
||||||
|
@ -3,8 +3,8 @@ import string
|
|||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'FieldGroup',
|
|
||||||
'InlineFields',
|
'InlineFields',
|
||||||
|
'ObjectAttribute',
|
||||||
'TabbedFieldGroups',
|
'TabbedFieldGroups',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,3 +41,9 @@ class TabbedFieldGroups:
|
|||||||
'fields': group.field_names,
|
'fields': group.field_names,
|
||||||
} for i, group in enumerate(self.groups, start=1)
|
} for i, group in enumerate(self.groups, start=1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectAttribute:
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
@ -12,6 +12,17 @@
|
|||||||
{# Single form field #}
|
{# Single form field #}
|
||||||
{% render_field items.0 %}
|
{% render_field items.0 %}
|
||||||
|
|
||||||
|
{% elif layout == 'attribute' %}
|
||||||
|
{# A static attribute of the form's instance #}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label class="col-sm-3 col-form-label text-lg-end required">{{ title }}</label>
|
||||||
|
<div class="col">
|
||||||
|
<div class="form-control-plaintext">
|
||||||
|
{{ items.0|linkify }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% elif layout == 'inline' %}
|
{% elif layout == 'inline' %}
|
||||||
{# Multiple form fields on the same line #}
|
{# Multiple form fields on the same line #}
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django import template
|
from django import template
|
||||||
|
|
||||||
from utilities.forms.rendering import InlineFields, TabbedFieldGroups
|
from utilities.forms.rendering import InlineFields, ObjectAttribute, TabbedFieldGroups
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'getfield',
|
'getfield',
|
||||||
@ -81,6 +81,13 @@ def render_fieldset(form, fieldset, heading=None):
|
|||||||
('tabs', None, tabs)
|
('tabs', None, tabs)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elif type(item) is ObjectAttribute:
|
||||||
|
value = getattr(form.instance, item.name)
|
||||||
|
label = value._meta.verbose_name if hasattr(value, '_meta') else item.name
|
||||||
|
rows.append(
|
||||||
|
('attribute', label.title(), [value])
|
||||||
|
)
|
||||||
|
|
||||||
# A single form field
|
# A single form field
|
||||||
elif item in form.fields:
|
elif item in form.fields:
|
||||||
rows.append(
|
rows.append(
|
||||||
|
Reference in New Issue
Block a user