Răsfoiți Sursa

Closes #1687: Enabled custom fields for services

Jeremy Stretch 7 ani în urmă
părinte
comite
b945dec41b

+ 5 - 5
netbox/extras/constants.py

@@ -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
-    'site', 'rack', 'devicetype', 'device',                 # DCIM
-    'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf',      # IPAM
-    'tenant',                                               # Tenancy
-    'cluster', 'virtualmachine',                            # Virtualization
+    'provider', 'circuit',                                         # Circuits
+    'site', 'rack', 'devicetype', 'device',                        # DCIM
+    'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service',  # IPAM
+    'tenant',                                                      # Tenancy
+    'cluster', 'virtualmachine',                                   # Virtualization
 )
 )
 
 
 # Custom field types
 # Custom field types

+ 3 - 3
netbox/ipam/api/serializers.py

@@ -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',
-            'last_updated',
+            'id', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description',
+            'custom_fields', 'created', 'last_updated',
         ]
         ]

+ 9 - 6
netbox/ipam/forms.py

@@ -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,
-    ChainedModelChoiceField, CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField,
-    Livesearch, ReturnURLForm, SlugField, add_blank_choice,
+    AnnotatedMultipleChoiceField, APISelect, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
+    CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, Livesearch, ReturnURLForm,
+    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)

+ 6 - 1
netbox/ipam/models.py

@@ -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'
 
 

+ 8 - 0
netbox/templates/ipam/service_edit.html

@@ -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 %}

+ 0 - 2
netbox/templates/ipam/service_list.html

@@ -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>