Просмотр исходного кода

Use ContentTypeChoiceField for all ContentType fields

Jeremy Stretch 4 лет назад
Родитель
Сommit
d82f2e289a

+ 19 - 34
netbox/extras/admin.py

@@ -1,16 +1,10 @@
 from django import forms
 from django.contrib import admin
+from django.contrib.contenttypes.models import ContentType
 
-from utilities.forms import LaxURLField
+from utilities.forms import ContentTypeChoiceField, ContentTypeMultipleChoiceField, LaxURLField
 from .models import CustomField, CustomLink, ExportTemplate, JobResult, Webhook
-
-
-def order_content_types(field):
-    """
-    Order the list of available ContentTypes by application
-    """
-    queryset = field.queryset.order_by('app_label', 'model')
-    field.choices = [(ct.pk, '{} > {}'.format(ct.app_label, ct.name)) for ct in queryset]
+from .utils import FeatureQuery
 
 
 #
@@ -18,6 +12,10 @@ def order_content_types(field):
 #
 
 class WebhookForm(forms.ModelForm):
+    content_types = ContentTypeMultipleChoiceField(
+        queryset=ContentType.objects.all(),
+        limit_choices_to=FeatureQuery('webhooks')
+    )
     payload_url = LaxURLField(
         label='URL'
     )
@@ -26,12 +24,6 @@ class WebhookForm(forms.ModelForm):
         model = Webhook
         exclude = ()
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        if 'content_types' in self.fields:
-            order_content_types(self.fields['content_types'])
-
 
 @admin.register(Webhook)
 class WebhookAdmin(admin.ModelAdmin):
@@ -70,6 +62,10 @@ class WebhookAdmin(admin.ModelAdmin):
 #
 
 class CustomFieldForm(forms.ModelForm):
+    content_types = ContentTypeMultipleChoiceField(
+        queryset=ContentType.objects.all(),
+        limit_choices_to=FeatureQuery('custom_fields')
+    )
 
     class Meta:
         model = CustomField
@@ -84,11 +80,6 @@ class CustomFieldForm(forms.ModelForm):
             )
         }
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        order_content_types(self.fields['content_types'])
-
 
 @admin.register(CustomField)
 class CustomFieldAdmin(admin.ModelAdmin):
@@ -127,6 +118,10 @@ class CustomFieldAdmin(admin.ModelAdmin):
 #
 
 class CustomLinkForm(forms.ModelForm):
+    content_type = ContentTypeChoiceField(
+        queryset=ContentType.objects.all(),
+        limit_choices_to=FeatureQuery('custom_links')
+    )
 
     class Meta:
         model = CustomLink
@@ -143,13 +138,6 @@ class CustomLinkForm(forms.ModelForm):
             'link_url': 'Jinja2 template code for the link URL. Reference the object as <code>{{ obj }}</code>.',
         }
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        # Format ContentType choices
-        order_content_types(self.fields['content_type'])
-        self.fields['content_type'].choices.insert(0, ('', '---------'))
-
 
 @admin.register(CustomLink)
 class CustomLinkAdmin(admin.ModelAdmin):
@@ -176,18 +164,15 @@ class CustomLinkAdmin(admin.ModelAdmin):
 #
 
 class ExportTemplateForm(forms.ModelForm):
+    content_type = ContentTypeChoiceField(
+        queryset=ContentType.objects.all(),
+        limit_choices_to=FeatureQuery('custom_links')
+    )
 
     class Meta:
         model = ExportTemplate
         exclude = []
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        # Format ContentType choices
-        order_content_types(self.fields['content_type'])
-        self.fields['content_type'].choices.insert(0, ('', '---------'))
-
 
 @admin.register(ExportTemplate)
 class ExportTemplateAdmin(admin.ModelAdmin):

+ 0 - 1
netbox/ipam/tests/test_views.py

@@ -329,7 +329,6 @@ class VLANGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
         cls.form_data = {
             'name': 'VLAN Group X',
             'slug': 'vlan-group-x',
-            'site': sites[1].pk,
             'description': 'A new VLAN group',
         }
 

+ 6 - 6
netbox/users/admin.py

@@ -4,9 +4,9 @@ from django.contrib.auth.admin import UserAdmin as UserAdmin_
 from django.contrib.auth.models import Group, User
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import FieldError, ValidationError
-from django.db.models import Q
 
-from extras.admin import order_content_types
+from utilities.forms.fields import ContentTypeMultipleChoiceField
+from .constants import *
 from .models import AdminGroup, AdminUser, ObjectPermission, Token, UserConfig
 
 
@@ -126,6 +126,10 @@ class TokenAdmin(admin.ModelAdmin):
 #
 
 class ObjectPermissionForm(forms.ModelForm):
+    object_types = ContentTypeMultipleChoiceField(
+        queryset=ContentType.objects.all(),
+        limit_choices_to=OBJECTPERMISSION_OBJECT_TYPES
+    )
     can_view = forms.BooleanField(required=False)
     can_add = forms.BooleanField(required=False)
     can_change = forms.BooleanField(required=False)
@@ -153,10 +157,6 @@ class ObjectPermissionForm(forms.ModelForm):
         # Make the actions field optional since the admin form uses it only for non-CRUD actions
         self.fields['actions'].required = False
 
-        # Format ContentType choices
-        order_content_types(self.fields['object_types'])
-        self.fields['object_types'].choices.insert(0, ('', '---------'))
-
         # Order group and user fields
         self.fields['groups'].queryset = self.fields['groups'].queryset.order_by('name')
         self.fields['users'].queryset = self.fields['users'].queryset.order_by('username')

+ 8 - 0
netbox/users/constants.py

@@ -0,0 +1,8 @@
+from django.db.models import Q
+
+
+OBJECTPERMISSION_OBJECT_TYPES = Q(
+    ~Q(app_label__in=['admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users']) |
+    Q(app_label='auth', model__in=['group', 'user']) |
+    Q(app_label='users', model__in=['objectpermission', 'token'])
+)

+ 2 - 6
netbox/users/models.py

@@ -6,7 +6,6 @@ from django.contrib.contenttypes.models import ContentType
 from django.contrib.postgres.fields import ArrayField
 from django.core.validators import MinLengthValidator
 from django.db import models
-from django.db.models import Q
 from django.db.models.signals import post_save
 from django.dispatch import receiver
 from django.utils import timezone
@@ -14,6 +13,7 @@ from django.utils import timezone
 from netbox.models import BigIDModel
 from utilities.querysets import RestrictedQuerySet
 from utilities.utils import flatten_dict
+from .constants import *
 
 
 __all__ = (
@@ -251,11 +251,7 @@ class ObjectPermission(BigIDModel):
     )
     object_types = models.ManyToManyField(
         to=ContentType,
-        limit_choices_to=Q(
-            ~Q(app_label__in=['admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users']) |
-            Q(app_label='auth', model__in=['group', 'user']) |
-            Q(app_label='users', model__in=['objectpermission', 'token'])
-        ),
+        limit_choices_to=OBJECTPERMISSION_OBJECT_TYPES,
         related_name='object_permissions'
     )
     groups = models.ManyToManyField(

+ 10 - 1
netbox/utilities/forms/fields.py

@@ -21,6 +21,7 @@ from .utils import expand_alphanumeric_pattern, expand_ipaddress_pattern
 __all__ = (
     'CommentField',
     'ContentTypeChoiceField',
+    'ContentTypeMultipleChoiceField',
     'CSVChoiceField',
     'CSVContentTypeField',
     'CSVDataField',
@@ -114,7 +115,7 @@ class JSONField(_JSONField):
         return json.dumps(value, sort_keys=True, indent=4)
 
 
-class ContentTypeChoiceField(forms.ModelChoiceField):
+class ContentTypeChoiceMixin:
 
     def __init__(self, queryset, *args, **kwargs):
         # Order ContentTypes by app_label
@@ -126,6 +127,14 @@ class ContentTypeChoiceField(forms.ModelChoiceField):
         return f'{meta.app_config.verbose_name} > {meta.verbose_name}'
 
 
+class ContentTypeChoiceField(ContentTypeChoiceMixin, forms.ModelChoiceField):
+    pass
+
+
+class ContentTypeMultipleChoiceField(ContentTypeChoiceMixin, forms.ModelMultipleChoiceField):
+    pass
+
+
 #
 # CSV fields
 #