Skip to content

Commit 4073ded

Browse files
Merge pull request #3932 from netbox-community/3892-contenttype-filtering
Closes #3892: Robust ContentType filtering
2 parents b98ac64 + bc696f2 commit 4073ded

16 files changed

+274
-172
lines changed

netbox/dcim/api/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,10 @@ class Meta:
609609

610610
class CableSerializer(ValidatedModelSerializer):
611611
termination_a_type = ContentTypeField(
612-
queryset=ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
612+
queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
613613
)
614614
termination_b_type = ContentTypeField(
615-
queryset=ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
615+
queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
616616
)
617617
termination_a = serializers.SerializerMethodField(read_only=True)
618618
termination_b = serializers.SerializerMethodField(read_only=True)

netbox/dcim/constants.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from django.db.models import Q
2+
13
from .choices import InterfaceTypeChoices
24

35

@@ -43,10 +45,21 @@
4345
]
4446

4547
# Cable endpoint types
46-
CABLE_TERMINATION_TYPES = [
47-
'consoleport', 'consoleserverport', 'interface', 'poweroutlet', 'powerport', 'frontport', 'rearport',
48-
'circuittermination', 'powerfeed',
49-
]
48+
CABLE_TERMINATION_MODELS = Q(
49+
Q(app_label='circuits', model__in=(
50+
'circuittermination',
51+
)) |
52+
Q(app_label='dcim', model__in=(
53+
'consoleport',
54+
'consoleserverport',
55+
'frontport',
56+
'interface',
57+
'powerfeed',
58+
'poweroutlet',
59+
'powerport',
60+
'rearport',
61+
))
62+
)
5063

5164
COMPATIBLE_TERMINATION_TYPES = {
5265
'consoleport': ['consoleserverport', 'frontport', 'rearport'],

netbox/dcim/forms.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,9 +3374,7 @@ class CableCSVForm(forms.ModelForm):
33743374
)
33753375
side_a_type = forms.ModelChoiceField(
33763376
queryset=ContentType.objects.all(),
3377-
limit_choices_to={
3378-
'model__in': CABLE_TERMINATION_TYPES,
3379-
},
3377+
limit_choices_to=CABLE_TERMINATION_MODELS,
33803378
to_field_name='model',
33813379
help_text='Side A type'
33823380
)
@@ -3395,9 +3393,7 @@ class CableCSVForm(forms.ModelForm):
33953393
)
33963394
side_b_type = forms.ModelChoiceField(
33973395
queryset=ContentType.objects.all(),
3398-
limit_choices_to={
3399-
'model__in': CABLE_TERMINATION_TYPES,
3400-
},
3396+
limit_choices_to=CABLE_TERMINATION_MODELS,
34013397
to_field_name='model',
34023398
help_text='Side B type'
34033399
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 2.2.8 on 2020-01-15 20:51
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('dcim', '0089_deterministic_ordering'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='cable',
16+
name='termination_a_type',
17+
field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType'),
18+
),
19+
migrations.AlterField(
20+
model_name='cable',
21+
name='termination_b_type',
22+
field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType'),
23+
),
24+
]

netbox/dcim/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,7 +1939,7 @@ class Cable(ChangeLoggedModel):
19391939
"""
19401940
termination_a_type = models.ForeignKey(
19411941
to=ContentType,
1942-
limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
1942+
limit_choices_to=CABLE_TERMINATION_MODELS,
19431943
on_delete=models.PROTECT,
19441944
related_name='+'
19451945
)
@@ -1950,7 +1950,7 @@ class Cable(ChangeLoggedModel):
19501950
)
19511951
termination_b_type = models.ForeignKey(
19521952
to=ContentType,
1953-
limit_choices_to={'model__in': CABLE_TERMINATION_TYPES},
1953+
limit_choices_to=CABLE_TERMINATION_MODELS,
19541954
on_delete=models.PROTECT,
19551955
related_name='+'
19561956
)

netbox/dcim/tests/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_choices(self):
3030
# Cable
3131
self.assertEqual(choices_to_dict(response.data.get('cable:length_unit')), CableLengthUnitChoices.as_dict())
3232
self.assertEqual(choices_to_dict(response.data.get('cable:status')), CableStatusChoices.as_dict())
33-
content_types = ContentType.objects.filter(model__in=CABLE_TERMINATION_TYPES)
33+
content_types = ContentType.objects.filter(CABLE_TERMINATION_MODELS)
3434
cable_termination_choices = {
3535
"{}.{}".format(ct.app_label, ct.model): ct.name for ct in content_types
3636
}

netbox/extras/api/serializers.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
ChoiceField, ContentTypeField, get_serializer_for_model, SerializerNotFound, SerializedPKRelatedField,
2121
ValidatedModelSerializer,
2222
)
23-
from utilities.utils import model_names_to_filter_dict
2423
from .nested_serializers import *
2524

2625

@@ -30,7 +29,7 @@
3029

3130
class GraphSerializer(ValidatedModelSerializer):
3231
type = ContentTypeField(
33-
queryset=ContentType.objects.filter(**model_names_to_filter_dict(GRAPH_MODELS)),
32+
queryset=ContentType.objects.filter(GRAPH_MODELS),
3433
)
3534

3635
class Meta:

0 commit comments

Comments
 (0)