1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #1687: Enabled custom fields for services

This commit is contained in:
Jeremy Stretch
2018-06-21 16:17:18 -04:00
parent 7819d9c112
commit b945dec41b
6 changed files with 31 additions and 17 deletions

View File

@ -3,11 +3,11 @@ from __future__ import unicode_literals
# Models which support custom fields # Models which support custom fields
CUSTOMFIELD_MODELS = ( CUSTOMFIELD_MODELS = (
'provider', 'circuit', # Circuits 'provider', 'circuit', # Circuits
'site', 'rack', 'devicetype', 'device', # DCIM 'site', 'rack', 'devicetype', 'device', # DCIM
'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', # IPAM 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service', # IPAM
'tenant', # Tenancy 'tenant', # Tenancy
'cluster', 'virtualmachine', # Virtualization 'cluster', 'virtualmachine', # Virtualization
) )
# Custom field types # Custom field types

View File

@ -301,7 +301,7 @@ class AvailableIPSerializer(serializers.Serializer):
# Services # Services
# #
class ServiceSerializer(ValidatedModelSerializer): class ServiceSerializer(CustomFieldModelSerializer):
device = NestedDeviceSerializer(required=False, allow_null=True) device = NestedDeviceSerializer(required=False, allow_null=True)
virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True) virtual_machine = NestedVirtualMachineSerializer(required=False, allow_null=True)
protocol = ChoiceFieldSerializer(choices=IP_PROTOCOL_CHOICES) protocol = ChoiceFieldSerializer(choices=IP_PROTOCOL_CHOICES)
@ -315,6 +315,6 @@ class ServiceSerializer(ValidatedModelSerializer):
class Meta: class Meta:
model = Service model = Service
fields = [ fields = [
'id', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description', 'created', 'id', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description',
'last_updated', 'custom_fields', 'created', 'last_updated',
] ]

View File

@ -11,9 +11,9 @@ from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFi
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
AnnotatedMultipleChoiceField, APISelect, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, AnnotatedMultipleChoiceField, APISelect, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
ChainedModelChoiceField, CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, ReturnURLForm,
Livesearch, ReturnURLForm, SlugField, add_blank_choice, SlugField, add_blank_choice,
) )
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .constants import ( from .constants import (
@ -917,7 +917,7 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
# Services # Services
# #
class ServiceForm(BootstrapMixin, forms.ModelForm): class ServiceForm(BootstrapMixin, CustomFieldForm):
class Meta: class Meta:
model = Service model = Service
@ -947,7 +947,10 @@ class ServiceForm(BootstrapMixin, forms.ModelForm):
class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm): class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
model = Service model = Service
q = forms.CharField(required=False, label='Search') q = forms.CharField(
required=False,
label='Search'
)
protocol = forms.ChoiceField( protocol = forms.ChoiceField(
choices=add_blank_choice(IP_PROTOCOL_CHOICES), choices=add_blank_choice(IP_PROTOCOL_CHOICES),
required=False required=False
@ -957,7 +960,7 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
) )
class ServiceBulkEditForm(BootstrapMixin, BulkEditForm): class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
pk = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), widget=forms.MultipleHiddenInput) pk = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), widget=forms.MultipleHiddenInput)
protocol = forms.ChoiceField(choices=add_blank_choice(IP_PROTOCOL_CHOICES), required=False) protocol = forms.ChoiceField(choices=add_blank_choice(IP_PROTOCOL_CHOICES), required=False)
port = forms.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(65535)], required=False) port = forms.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(65535)], required=False)

View File

@ -835,7 +835,7 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
@python_2_unicode_compatible @python_2_unicode_compatible
class Service(CreatedUpdatedModel): class Service(CreatedUpdatedModel, CustomFieldModel):
""" """
A Service represents a layer-four service (e.g. HTTP or SSH) running on a Device or VirtualMachine. A Service may A Service represents a layer-four service (e.g. HTTP or SSH) running on a Device or VirtualMachine. A Service may
optionally be tied to one or more specific IPAddresses belonging to its parent. optionally be tied to one or more specific IPAddresses belonging to its parent.
@ -875,6 +875,11 @@ class Service(CreatedUpdatedModel):
max_length=100, max_length=100,
blank=True blank=True
) )
custom_field_values = GenericRelation(
to='extras.CustomFieldValue',
content_type_field='obj_type',
object_id_field='obj_id'
)
serializer = 'ipam.api.serializers.ServiceSerializer' serializer = 'ipam.api.serializers.ServiceSerializer'

View File

@ -32,4 +32,12 @@
{% render_field form.description %} {% render_field form.description %}
</div> </div>
</div> </div>
{% if form.custom_fields %}
<div class="panel panel-default">
<div class="panel-heading"><strong>Custom Fields</strong></div>
<div class="panel-body">
{% render_custom_fields form %}
</div>
</div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -1,6 +1,4 @@
{% extends '_base.html' %} {% extends '_base.html' %}
{% load buttons %}
{% load humanize %}
{% block content %} {% block content %}
<h1>{% block title %}Services{% endblock %}</h1> <h1>{% block title %}Services{% endblock %}</h1>