We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Attaching a cloneable multi selection custom field with custom field choices breaks the Clone function
### NetBox version

v3.6.3

### Python version

3.9

### Steps to Reproduce

1. Create a custom field choices object without base choices selected and with at least 1 extra choice defined.
2. Create a custom field of the type "Multiple Selection" and associate with a content type (I used Virtual Machine, but the problem also appears for all other object types I've tested with such as IP addresses). 
3. Use the previously created custom field choices object as "Choice Set".
4. Select the "Is cloneable" checkbox.
5. Go to any object of the associated content type and try to clone it. It doesn't matter if the custom field has been provided with a value for that object or not.
6. Cloning will fail with the message `<class 'TypeError'> 'in <string>' requires string as left operand, not NoneType`
7. Disable the "Is cloneable" checkbox in the custom field that was created in step 2.
8. Cloning the object will now work (but obviously without cloning the custom field).

### Expected Behavior

I would expect the object to be cloneable when I use custom fields of the multiple selection type with the cloneable option enabled.

### Observed Behavior

`<class 'TypeError'>'in <string>' requires string as left operand, not NoneType` occurs whenever trying to clone any object that uses a multiple selection custom field where "is cloneable" is enabled.

This worked fine in 3.5.9, so it seems it is probably related to the new custom field choices object introduced in 3.6.0.

The workaround for now is to disable "is cloneable" on all multiple selection custom fields until the cause of the error is fixed.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `netbox/utilities/forms/fields/dynamic.py`
Content:
```
1 import django_filters
2 from django import forms
3 from django.conf import settings
4 from django.forms import BoundField
5 from django.urls import reverse
6 
7 from utilities.forms import widgets
8 from utilities.utils import get_viewname
9 
10 __all__ = (
11     'DynamicChoiceField',
12     'DynamicModelChoiceField',
13     'DynamicModelMultipleChoiceField',
14     'DynamicMultipleChoiceField',
15 )
16 
17 
18 #
19 # Choice fields
20 #
21 
22 class DynamicChoiceField(forms.ChoiceField):
23 
24     def get_bound_field(self, form, field_name):
25         bound_field = BoundField(form, self, field_name)
26         data = bound_field.value()
27 
28         if data is not None:
29             self.choices = [
30                 choice for choice in self.choices if choice[0] == data
31             ]
32         else:
33             self.choices = []
34 
35         return bound_field
36 
37 
38 class DynamicMultipleChoiceField(forms.MultipleChoiceField):
39 
40     def get_bound_field(self, form, field_name):
41         bound_field = BoundField(form, self, field_name)
42         data = bound_field.value()
43 
44         if data is not None:
45             self.choices = [
46                 choice for choice in self.choices if choice[0] in data
47             ]
48 
49         return bound_field
50 
51 
52 #
53 # Model choice fields
54 #
55 
56 class DynamicModelChoiceMixin:
57     """
58     Override `get_bound_field()` to avoid pre-populating field choices with a SQL query. The field will be
59     rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget.
60 
61     Attributes:
62         query_params: A dictionary of additional key/value pairs to attach to the API request
63         initial_params: A dictionary of child field references to use for selecting a parent field's initial value
64         null_option: The string used to represent a null selection (if any)
65         disabled_indicator: The name of the field which, if populated, will disable selection of the
66             choice (optional)
67         fetch_trigger: The event type which will cause the select element to
68             fetch data from the API. Must be 'load', 'open', or 'collapse'. (optional)
69         selector: Include an advanced object selection widget to assist the user in identifying the desired object
70     """
71     filter = django_filters.ModelChoiceFilter
72     widget = widgets.APISelect
73 
74     def __init__(
75             self,
76             queryset,
77             *,
78             query_params=None,
79             initial_params=None,
80             null_option=None,
81             disabled_indicator=None,
82             fetch_trigger=None,
83             empty_label=None,
84             selector=False,
85             **kwargs
86     ):
87         self.model = queryset.model
88         self.query_params = query_params or {}
89         self.initial_params = initial_params or {}
90         self.null_option = null_option
91         self.disabled_indicator = disabled_indicator
92         self.fetch_trigger = fetch_trigger
93         self.selector = selector
94 
95         # to_field_name is set by ModelChoiceField.__init__(), but we need to set it early for reference
96         # by widget_attrs()
97         self.to_field_name = kwargs.get('to_field_name')
98         self.empty_option = empty_label or ""
99 
100         super().__init__(queryset, **kwargs)
101 
102     def widget_attrs(self, widget):
103         attrs = {
104             'data-empty-option': self.empty_option
105         }
106 
107         # Set value-field attribute if the field specifies to_field_name
108         if self.to_field_name:
109             attrs['value-field'] = self.to_field_name
110 
111         # Set the string used to represent a null option
112         if self.null_option is not None:
113             attrs['data-null-option'] = self.null_option
114 
115         # Set the disabled indicator, if any
116         if self.disabled_indicator is not None:
117             attrs['disabled-indicator'] = self.disabled_indicator
118 
119         # Set the fetch trigger, if any.
120         if self.fetch_trigger is not None:
121             attrs['data-fetch-trigger'] = self.fetch_trigger
122 
123         # Attach any static query parameters
124         if (len(self.query_params) > 0):
125             widget.add_query_params(self.query_params)
126 
127         # Include object selector?
128         if self.selector:
129             attrs['selector'] = self.model._meta.label_lower
130 
131         return attrs
132 
133     def get_bound_field(self, form, field_name):
134         bound_field = BoundField(form, self, field_name)
135 
136         # Set initial value based on prescribed child fields (if not already set)
137         if not self.initial and self.initial_params:
138             filter_kwargs = {}
139             for kwarg, child_field in self.initial_params.items():
140                 value = form.initial.get(child_field.lstrip('$'))
141                 if value:
142                     filter_kwargs[kwarg] = value
143             if filter_kwargs:
144                 self.initial = self.queryset.filter(**filter_kwargs).first()
145 
146         # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options
147         # will be populated on-demand via the APISelect widget.
148         data = bound_field.value()
149 
150         if data:
151             # When the field is multiple choice pass the data as a list if it's not already
152             if isinstance(bound_field.field, DynamicModelMultipleChoiceField) and not type(data) is list:
153                 data = [data]
154 
155             field_name = getattr(self, 'to_field_name') or 'pk'
156             filter = self.filter(field_name=field_name)
157             try:
158                 self.queryset = filter.filter(self.queryset, data)
159             except (TypeError, ValueError):
160                 # Catch any error caused by invalid initial data passed from the user
161                 self.queryset = self.queryset.none()
162         else:
163             self.queryset = self.queryset.none()
164 
165         # Set the data URL on the APISelect widget (if not already set)
166         widget = bound_field.field.widget
167         if not widget.attrs.get('data-url'):
168             viewname = get_viewname(self.queryset.model, action='list', rest_api=True)
169             widget.attrs['data-url'] = reverse(viewname)
170 
171         return bound_field
172 
173 
174 class DynamicModelChoiceField(DynamicModelChoiceMixin, forms.ModelChoiceField):
175     """
176     Dynamic selection field for a single object, backed by NetBox's REST API.
177     """
178     def clean(self, value):
179         """
180         When null option is enabled and "None" is sent as part of a form to be submitted, it is sent as the
181         string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.
182         """
183         if self.null_option is not None and value == settings.FILTERS_NULL_CHOICE_VALUE:
184             return None
185         return super().clean(value)
186 
187 
188 class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultipleChoiceField):
189     """
190     A multiple-choice version of `DynamicModelChoiceField`.
191     """
192     filter = django_filters.ModelMultipleChoiceFilter
193     widget = widgets.APISelectMultiple
194 
195     def clean(self, value):
196         value = value or []
197 
198         # When null option is enabled and "None" is sent as part of a form to be submitted, it is sent as the
199         # string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.
200         if self.null_option is not None and settings.FILTERS_NULL_CHOICE_VALUE in value:
201             value = [v for v in value if v != settings.FILTERS_NULL_CHOICE_VALUE]
202             return [None, *value]
203 
204         return super().clean(value)
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/netbox/utilities/forms/fields/dynamic.py b/netbox/utilities/forms/fields/dynamic.py
--- a/netbox/utilities/forms/fields/dynamic.py
+++ b/netbox/utilities/forms/fields/dynamic.py
@@ -43,7 +43,7 @@
 
         if data is not None:
             self.choices = [
-                choice for choice in self.choices if choice[0] in data
+                choice for choice in self.choices if choice[0] and choice[0] in data
             ]
 
         return bound_field

{"golden_diff": "diff --git a/netbox/utilities/forms/fields/dynamic.py b/netbox/utilities/forms/fields/dynamic.py\n--- a/netbox/utilities/forms/fields/dynamic.py\n+++ b/netbox/utilities/forms/fields/dynamic.py\n@@ -43,7 +43,7 @@\n \n         if data is not None:\n             self.choices = [\n-                choice for choice in self.choices if choice[0] in data\n+                choice for choice in self.choices if choice[0] and choice[0] in data\n             ]\n \n         return bound_field\n", "issue": "Attaching a cloneable multi selection custom field with custom field choices breaks the Clone function\n### NetBox version\n\nv3.6.3\n\n### Python version\n\n3.9\n\n### Steps to Reproduce\n\n1. Create a custom field choices object without base choices selected and with at least 1 extra choice defined.\r\n2. Create a custom field of the type \"Multiple Selection\" and associate with a content type (I used Virtual Machine, but the problem also appears for all other object types I've tested with such as IP addresses). \r\n3. Use the previously created custom field choices object as \"Choice Set\".\r\n4. Select the \"Is cloneable\" checkbox.\r\n5. Go to any object of the associated content type and try to clone it. It doesn't matter if the custom field has been provided with a value for that object or not.\r\n6. Cloning will fail with the message `<class 'TypeError'> 'in <string>' requires string as left operand, not NoneType`\r\n7. Disable the \"Is cloneable\" checkbox in the custom field that was created in step 2.\r\n8. Cloning the object will now work (but obviously without cloning the custom field).\n\n### Expected Behavior\n\nI would expect the object to be cloneable when I use custom fields of the multiple selection type with the cloneable option enabled.\n\n### Observed Behavior\n\n`<class 'TypeError'>'in <string>' requires string as left operand, not NoneType` occurs whenever trying to clone any object that uses a multiple selection custom field where \"is cloneable\" is enabled.\r\n\r\nThis worked fine in 3.5.9, so it seems it is probably related to the new custom field choices object introduced in 3.6.0.\r\n\r\nThe workaround for now is to disable \"is cloneable\" on all multiple selection custom fields until the cause of the error is fixed.\n", "before_files": [{"content": "import django_filters\nfrom django import forms\nfrom django.conf import settings\nfrom django.forms import BoundField\nfrom django.urls import reverse\n\nfrom utilities.forms import widgets\nfrom utilities.utils import get_viewname\n\n__all__ = (\n    'DynamicChoiceField',\n    'DynamicModelChoiceField',\n    'DynamicModelMultipleChoiceField',\n    'DynamicMultipleChoiceField',\n)\n\n\n#\n# Choice fields\n#\n\nclass DynamicChoiceField(forms.ChoiceField):\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n        data = bound_field.value()\n\n        if data is not None:\n            self.choices = [\n                choice for choice in self.choices if choice[0] == data\n            ]\n        else:\n            self.choices = []\n\n        return bound_field\n\n\nclass DynamicMultipleChoiceField(forms.MultipleChoiceField):\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n        data = bound_field.value()\n\n        if data is not None:\n            self.choices = [\n                choice for choice in self.choices if choice[0] in data\n            ]\n\n        return bound_field\n\n\n#\n# Model choice fields\n#\n\nclass DynamicModelChoiceMixin:\n    \"\"\"\n    Override `get_bound_field()` to avoid pre-populating field choices with a SQL query. The field will be\n    rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget.\n\n    Attributes:\n        query_params: A dictionary of additional key/value pairs to attach to the API request\n        initial_params: A dictionary of child field references to use for selecting a parent field's initial value\n        null_option: The string used to represent a null selection (if any)\n        disabled_indicator: The name of the field which, if populated, will disable selection of the\n            choice (optional)\n        fetch_trigger: The event type which will cause the select element to\n            fetch data from the API. Must be 'load', 'open', or 'collapse'. (optional)\n        selector: Include an advanced object selection widget to assist the user in identifying the desired object\n    \"\"\"\n    filter = django_filters.ModelChoiceFilter\n    widget = widgets.APISelect\n\n    def __init__(\n            self,\n            queryset,\n            *,\n            query_params=None,\n            initial_params=None,\n            null_option=None,\n            disabled_indicator=None,\n            fetch_trigger=None,\n            empty_label=None,\n            selector=False,\n            **kwargs\n    ):\n        self.model = queryset.model\n        self.query_params = query_params or {}\n        self.initial_params = initial_params or {}\n        self.null_option = null_option\n        self.disabled_indicator = disabled_indicator\n        self.fetch_trigger = fetch_trigger\n        self.selector = selector\n\n        # to_field_name is set by ModelChoiceField.__init__(), but we need to set it early for reference\n        # by widget_attrs()\n        self.to_field_name = kwargs.get('to_field_name')\n        self.empty_option = empty_label or \"\"\n\n        super().__init__(queryset, **kwargs)\n\n    def widget_attrs(self, widget):\n        attrs = {\n            'data-empty-option': self.empty_option\n        }\n\n        # Set value-field attribute if the field specifies to_field_name\n        if self.to_field_name:\n            attrs['value-field'] = self.to_field_name\n\n        # Set the string used to represent a null option\n        if self.null_option is not None:\n            attrs['data-null-option'] = self.null_option\n\n        # Set the disabled indicator, if any\n        if self.disabled_indicator is not None:\n            attrs['disabled-indicator'] = self.disabled_indicator\n\n        # Set the fetch trigger, if any.\n        if self.fetch_trigger is not None:\n            attrs['data-fetch-trigger'] = self.fetch_trigger\n\n        # Attach any static query parameters\n        if (len(self.query_params) > 0):\n            widget.add_query_params(self.query_params)\n\n        # Include object selector?\n        if self.selector:\n            attrs['selector'] = self.model._meta.label_lower\n\n        return attrs\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n\n        # Set initial value based on prescribed child fields (if not already set)\n        if not self.initial and self.initial_params:\n            filter_kwargs = {}\n            for kwarg, child_field in self.initial_params.items():\n                value = form.initial.get(child_field.lstrip('$'))\n                if value:\n                    filter_kwargs[kwarg] = value\n            if filter_kwargs:\n                self.initial = self.queryset.filter(**filter_kwargs).first()\n\n        # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options\n        # will be populated on-demand via the APISelect widget.\n        data = bound_field.value()\n\n        if data:\n            # When the field is multiple choice pass the data as a list if it's not already\n            if isinstance(bound_field.field, DynamicModelMultipleChoiceField) and not type(data) is list:\n                data = [data]\n\n            field_name = getattr(self, 'to_field_name') or 'pk'\n            filter = self.filter(field_name=field_name)\n            try:\n                self.queryset = filter.filter(self.queryset, data)\n            except (TypeError, ValueError):\n                # Catch any error caused by invalid initial data passed from the user\n                self.queryset = self.queryset.none()\n        else:\n            self.queryset = self.queryset.none()\n\n        # Set the data URL on the APISelect widget (if not already set)\n        widget = bound_field.field.widget\n        if not widget.attrs.get('data-url'):\n            viewname = get_viewname(self.queryset.model, action='list', rest_api=True)\n            widget.attrs['data-url'] = reverse(viewname)\n\n        return bound_field\n\n\nclass DynamicModelChoiceField(DynamicModelChoiceMixin, forms.ModelChoiceField):\n    \"\"\"\n    Dynamic selection field for a single object, backed by NetBox's REST API.\n    \"\"\"\n    def clean(self, value):\n        \"\"\"\n        When null option is enabled and \"None\" is sent as part of a form to be submitted, it is sent as the\n        string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.\n        \"\"\"\n        if self.null_option is not None and value == settings.FILTERS_NULL_CHOICE_VALUE:\n            return None\n        return super().clean(value)\n\n\nclass DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultipleChoiceField):\n    \"\"\"\n    A multiple-choice version of `DynamicModelChoiceField`.\n    \"\"\"\n    filter = django_filters.ModelMultipleChoiceFilter\n    widget = widgets.APISelectMultiple\n\n    def clean(self, value):\n        value = value or []\n\n        # When null option is enabled and \"None\" is sent as part of a form to be submitted, it is sent as the\n        # string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.\n        if self.null_option is not None and settings.FILTERS_NULL_CHOICE_VALUE in value:\n            value = [v for v in value if v != settings.FILTERS_NULL_CHOICE_VALUE]\n            return [None, *value]\n\n        return super().clean(value)\n", "path": "netbox/utilities/forms/fields/dynamic.py"}], "after_files": [{"content": "import django_filters\nfrom django import forms\nfrom django.conf import settings\nfrom django.forms import BoundField\nfrom django.urls import reverse\n\nfrom utilities.forms import widgets\nfrom utilities.utils import get_viewname\n\n__all__ = (\n    'DynamicChoiceField',\n    'DynamicModelChoiceField',\n    'DynamicModelMultipleChoiceField',\n    'DynamicMultipleChoiceField',\n)\n\n\n#\n# Choice fields\n#\n\nclass DynamicChoiceField(forms.ChoiceField):\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n        data = bound_field.value()\n\n        if data is not None:\n            self.choices = [\n                choice for choice in self.choices if choice[0] == data\n            ]\n        else:\n            self.choices = []\n\n        return bound_field\n\n\nclass DynamicMultipleChoiceField(forms.MultipleChoiceField):\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n        data = bound_field.value()\n\n        if data is not None:\n            self.choices = [\n                choice for choice in self.choices if choice[0] and choice[0] in data\n            ]\n\n        return bound_field\n\n\n#\n# Model choice fields\n#\n\nclass DynamicModelChoiceMixin:\n    \"\"\"\n    Override `get_bound_field()` to avoid pre-populating field choices with a SQL query. The field will be\n    rendered only with choices set via bound data. Choices are populated on-demand via the APISelect widget.\n\n    Attributes:\n        query_params: A dictionary of additional key/value pairs to attach to the API request\n        initial_params: A dictionary of child field references to use for selecting a parent field's initial value\n        null_option: The string used to represent a null selection (if any)\n        disabled_indicator: The name of the field which, if populated, will disable selection of the\n            choice (optional)\n        fetch_trigger: The event type which will cause the select element to\n            fetch data from the API. Must be 'load', 'open', or 'collapse'. (optional)\n        selector: Include an advanced object selection widget to assist the user in identifying the desired object\n    \"\"\"\n    filter = django_filters.ModelChoiceFilter\n    widget = widgets.APISelect\n\n    def __init__(\n            self,\n            queryset,\n            *,\n            query_params=None,\n            initial_params=None,\n            null_option=None,\n            disabled_indicator=None,\n            fetch_trigger=None,\n            empty_label=None,\n            selector=False,\n            **kwargs\n    ):\n        self.model = queryset.model\n        self.query_params = query_params or {}\n        self.initial_params = initial_params or {}\n        self.null_option = null_option\n        self.disabled_indicator = disabled_indicator\n        self.fetch_trigger = fetch_trigger\n        self.selector = selector\n\n        # to_field_name is set by ModelChoiceField.__init__(), but we need to set it early for reference\n        # by widget_attrs()\n        self.to_field_name = kwargs.get('to_field_name')\n        self.empty_option = empty_label or \"\"\n\n        super().__init__(queryset, **kwargs)\n\n    def widget_attrs(self, widget):\n        attrs = {\n            'data-empty-option': self.empty_option\n        }\n\n        # Set value-field attribute if the field specifies to_field_name\n        if self.to_field_name:\n            attrs['value-field'] = self.to_field_name\n\n        # Set the string used to represent a null option\n        if self.null_option is not None:\n            attrs['data-null-option'] = self.null_option\n\n        # Set the disabled indicator, if any\n        if self.disabled_indicator is not None:\n            attrs['disabled-indicator'] = self.disabled_indicator\n\n        # Set the fetch trigger, if any.\n        if self.fetch_trigger is not None:\n            attrs['data-fetch-trigger'] = self.fetch_trigger\n\n        # Attach any static query parameters\n        if (len(self.query_params) > 0):\n            widget.add_query_params(self.query_params)\n\n        # Include object selector?\n        if self.selector:\n            attrs['selector'] = self.model._meta.label_lower\n\n        return attrs\n\n    def get_bound_field(self, form, field_name):\n        bound_field = BoundField(form, self, field_name)\n\n        # Set initial value based on prescribed child fields (if not already set)\n        if not self.initial and self.initial_params:\n            filter_kwargs = {}\n            for kwarg, child_field in self.initial_params.items():\n                value = form.initial.get(child_field.lstrip('$'))\n                if value:\n                    filter_kwargs[kwarg] = value\n            if filter_kwargs:\n                self.initial = self.queryset.filter(**filter_kwargs).first()\n\n        # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options\n        # will be populated on-demand via the APISelect widget.\n        data = bound_field.value()\n\n        if data:\n            # When the field is multiple choice pass the data as a list if it's not already\n            if isinstance(bound_field.field, DynamicModelMultipleChoiceField) and not type(data) is list:\n                data = [data]\n\n            field_name = getattr(self, 'to_field_name') or 'pk'\n            filter = self.filter(field_name=field_name)\n            try:\n                self.queryset = filter.filter(self.queryset, data)\n            except (TypeError, ValueError):\n                # Catch any error caused by invalid initial data passed from the user\n                self.queryset = self.queryset.none()\n        else:\n            self.queryset = self.queryset.none()\n\n        # Set the data URL on the APISelect widget (if not already set)\n        widget = bound_field.field.widget\n        if not widget.attrs.get('data-url'):\n            viewname = get_viewname(self.queryset.model, action='list', rest_api=True)\n            widget.attrs['data-url'] = reverse(viewname)\n\n        return bound_field\n\n\nclass DynamicModelChoiceField(DynamicModelChoiceMixin, forms.ModelChoiceField):\n    \"\"\"\n    Dynamic selection field for a single object, backed by NetBox's REST API.\n    \"\"\"\n    def clean(self, value):\n        \"\"\"\n        When null option is enabled and \"None\" is sent as part of a form to be submitted, it is sent as the\n        string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.\n        \"\"\"\n        if self.null_option is not None and value == settings.FILTERS_NULL_CHOICE_VALUE:\n            return None\n        return super().clean(value)\n\n\nclass DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultipleChoiceField):\n    \"\"\"\n    A multiple-choice version of `DynamicModelChoiceField`.\n    \"\"\"\n    filter = django_filters.ModelMultipleChoiceFilter\n    widget = widgets.APISelectMultiple\n\n    def clean(self, value):\n        value = value or []\n\n        # When null option is enabled and \"None\" is sent as part of a form to be submitted, it is sent as the\n        # string 'null'.  This will check for that condition and gracefully handle the conversion to a NoneType.\n        if self.null_option is not None and settings.FILTERS_NULL_CHOICE_VALUE in value:\n            value = [v for v in value if v != settings.FILTERS_NULL_CHOICE_VALUE]\n            return [None, *value]\n\n        return super().clean(value)\n", "path": "netbox/utilities/forms/fields/dynamic.py"}]}