We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove Custom Fields from Admin UI
### Proposed Changes

Remove custom fields from Admin UI. This should be as simple as deleting a bunch of code from `nautobot/extras/admin.py` that's no longer needed.

### Justification

Now that we have custom field management in the regular UI (#735, #997), the admin UI for custom field management is redundant.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nautobot/extras/admin.py`
Content:
```
1 from db_file_storage.form_widgets import DBAdminClearableFileInput
2 from django import forms
3 from django.contrib import admin, messages
4 from django.db import transaction
5 from django.db.models import ProtectedError
6 
7 from .models import CustomField, CustomFieldChoice, FileProxy, JobResult
8 
9 
10 def order_content_types(field):
11     """
12     Order the list of available ContentTypes by application
13     """
14     queryset = field.queryset.order_by("app_label", "model")
15     field.choices = [(ct.pk, "{} > {}".format(ct.app_label, ct.name)) for ct in queryset]
16 
17 
18 #
19 # Custom fields
20 #
21 
22 
23 class CustomFieldForm(forms.ModelForm):
24     class Meta:
25         model = CustomField
26         exclude = []
27         widgets = {
28             "default": forms.TextInput(),
29             "validation_regex": forms.Textarea(
30                 attrs={
31                     "cols": 80,
32                     "rows": 3,
33                 }
34             ),
35         }
36 
37     def __init__(self, *args, **kwargs):
38         super().__init__(*args, **kwargs)
39 
40         order_content_types(self.fields["content_types"])
41 
42 
43 class CustomFieldChoiceAdmin(admin.TabularInline):
44     """
45     Defines the inline formset factory that handles choices for selection type custom fields.
46     The `extra` defines the default number of inline rows that appear in the UI.
47     """
48 
49     model = CustomFieldChoice
50     extra = 5
51 
52 
53 @admin.register(CustomField)
54 class CustomFieldAdmin(admin.ModelAdmin):
55     """
56     Define the structure and composition of the custom field form in the admin panel.
57     """
58 
59     actions = None
60     form = CustomFieldForm
61     inlines = [CustomFieldChoiceAdmin]
62     list_display = [
63         "name",
64         "models",
65         "type",
66         "required",
67         "filter_logic",
68         "default",
69         "weight",
70         "description",
71     ]
72     list_filter = [
73         "type",
74         "required",
75         "content_types",
76     ]
77     fieldsets = (
78         (
79             "Custom Field",
80             {
81                 "fields": (
82                     "type",
83                     "name",
84                     "weight",
85                     "label",
86                     "description",
87                     "required",
88                     "default",
89                     "filter_logic",
90                 )
91             },
92         ),
93         (
94             "Assignment",
95             {
96                 "description": "A custom field must be assigned to one or more object types.",
97                 "fields": ("content_types",),
98             },
99         ),
100         (
101             "Validation Rules",
102             {
103                 "fields": (
104                     "validation_minimum",
105                     "validation_maximum",
106                     "validation_regex",
107                 ),
108                 "classes": ("monospace",),
109             },
110         ),
111     )
112 
113     def models(self, obj):
114         return ", ".join([ct.name for ct in obj.content_types.all()])
115 
116     @transaction.atomic
117     def save_formset(self, request, form, formset, change):
118         # TODO(John): revisit this when custom fields are moved out of admin... there is a better way...
119         if formset.model != CustomFieldChoice:
120             return super().save_formset(request, form, formset, change)
121         instances = formset.save(commit=False)
122         for instance in instances:
123             instance.save()
124         formset.save_m2m()
125         for obj in formset.deleted_objects:
126             try:
127                 obj.delete()
128             except ProtectedError as e:
129                 self.message_user(request, e, level=messages.ERROR)
130                 raise e
131 
132 
133 #
134 # File attachments
135 #
136 
137 
138 class FileProxyForm(forms.ModelForm):
139     class Meta:
140         model = FileProxy
141         exclude = []
142         widgets = {
143             "file": DBAdminClearableFileInput,
144         }
145 
146 
147 @admin.register(FileProxy)
148 class FileProxyAdmin(admin.ModelAdmin):
149     form = FileProxyForm
150     list_display = ["name", "uploaded_at"]
151     list_filter = ["uploaded_at"]
152 
153 
154 #
155 # Job results (jobs, scripts, reports, Git repository sync, etc.)
156 #
157 
158 
159 @admin.register(JobResult)
160 class JobResultAdmin(admin.ModelAdmin):
161     list_display = [
162         "obj_type",
163         "name",
164         "created",
165         "completed",
166         "user",
167         "status",
168     ]
169     fields = [
170         "obj_type",
171         "name",
172         "created",
173         "completed",
174         "user",
175         "status",
176         "data",
177         "job_id",
178     ]
179     list_filter = [
180         "status",
181     ]
182     readonly_fields = fields
183 
184     def has_add_permission(self, request):
185         return False
186
```
--- 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/nautobot/extras/admin.py b/nautobot/extras/admin.py
--- a/nautobot/extras/admin.py
+++ b/nautobot/extras/admin.py
@@ -1,10 +1,8 @@
 from db_file_storage.form_widgets import DBAdminClearableFileInput
 from django import forms
-from django.contrib import admin, messages
-from django.db import transaction
-from django.db.models import ProtectedError
+from django.contrib import admin
 
-from .models import CustomField, CustomFieldChoice, FileProxy, JobResult
+from .models import FileProxy, JobResult
 
 
 def order_content_types(field):
@@ -15,121 +13,6 @@
     field.choices = [(ct.pk, "{} > {}".format(ct.app_label, ct.name)) for ct in queryset]
 
 
-#
-# Custom fields
-#
-
-
-class CustomFieldForm(forms.ModelForm):
-    class Meta:
-        model = CustomField
-        exclude = []
-        widgets = {
-            "default": forms.TextInput(),
-            "validation_regex": forms.Textarea(
-                attrs={
-                    "cols": 80,
-                    "rows": 3,
-                }
-            ),
-        }
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        order_content_types(self.fields["content_types"])
-
-
-class CustomFieldChoiceAdmin(admin.TabularInline):
-    """
-    Defines the inline formset factory that handles choices for selection type custom fields.
-    The `extra` defines the default number of inline rows that appear in the UI.
-    """
-
-    model = CustomFieldChoice
-    extra = 5
-
-
-@admin.register(CustomField)
-class CustomFieldAdmin(admin.ModelAdmin):
-    """
-    Define the structure and composition of the custom field form in the admin panel.
-    """
-
-    actions = None
-    form = CustomFieldForm
-    inlines = [CustomFieldChoiceAdmin]
-    list_display = [
-        "name",
-        "models",
-        "type",
-        "required",
-        "filter_logic",
-        "default",
-        "weight",
-        "description",
-    ]
-    list_filter = [
-        "type",
-        "required",
-        "content_types",
-    ]
-    fieldsets = (
-        (
-            "Custom Field",
-            {
-                "fields": (
-                    "type",
-                    "name",
-                    "weight",
-                    "label",
-                    "description",
-                    "required",
-                    "default",
-                    "filter_logic",
-                )
-            },
-        ),
-        (
-            "Assignment",
-            {
-                "description": "A custom field must be assigned to one or more object types.",
-                "fields": ("content_types",),
-            },
-        ),
-        (
-            "Validation Rules",
-            {
-                "fields": (
-                    "validation_minimum",
-                    "validation_maximum",
-                    "validation_regex",
-                ),
-                "classes": ("monospace",),
-            },
-        ),
-    )
-
-    def models(self, obj):
-        return ", ".join([ct.name for ct in obj.content_types.all()])
-
-    @transaction.atomic
-    def save_formset(self, request, form, formset, change):
-        # TODO(John): revisit this when custom fields are moved out of admin... there is a better way...
-        if formset.model != CustomFieldChoice:
-            return super().save_formset(request, form, formset, change)
-        instances = formset.save(commit=False)
-        for instance in instances:
-            instance.save()
-        formset.save_m2m()
-        for obj in formset.deleted_objects:
-            try:
-                obj.delete()
-            except ProtectedError as e:
-                self.message_user(request, e, level=messages.ERROR)
-                raise e
-
-
 #
 # File attachments
 #

{"golden_diff": "diff --git a/nautobot/extras/admin.py b/nautobot/extras/admin.py\n--- a/nautobot/extras/admin.py\n+++ b/nautobot/extras/admin.py\n@@ -1,10 +1,8 @@\n from db_file_storage.form_widgets import DBAdminClearableFileInput\n from django import forms\n-from django.contrib import admin, messages\n-from django.db import transaction\n-from django.db.models import ProtectedError\n+from django.contrib import admin\n \n-from .models import CustomField, CustomFieldChoice, FileProxy, JobResult\n+from .models import FileProxy, JobResult\n \n \n def order_content_types(field):\n@@ -15,121 +13,6 @@\n     field.choices = [(ct.pk, \"{} > {}\".format(ct.app_label, ct.name)) for ct in queryset]\n \n \n-#\n-# Custom fields\n-#\n-\n-\n-class CustomFieldForm(forms.ModelForm):\n-    class Meta:\n-        model = CustomField\n-        exclude = []\n-        widgets = {\n-            \"default\": forms.TextInput(),\n-            \"validation_regex\": forms.Textarea(\n-                attrs={\n-                    \"cols\": 80,\n-                    \"rows\": 3,\n-                }\n-            ),\n-        }\n-\n-    def __init__(self, *args, **kwargs):\n-        super().__init__(*args, **kwargs)\n-\n-        order_content_types(self.fields[\"content_types\"])\n-\n-\n-class CustomFieldChoiceAdmin(admin.TabularInline):\n-    \"\"\"\n-    Defines the inline formset factory that handles choices for selection type custom fields.\n-    The `extra` defines the default number of inline rows that appear in the UI.\n-    \"\"\"\n-\n-    model = CustomFieldChoice\n-    extra = 5\n-\n-\n-@admin.register(CustomField)\n-class CustomFieldAdmin(admin.ModelAdmin):\n-    \"\"\"\n-    Define the structure and composition of the custom field form in the admin panel.\n-    \"\"\"\n-\n-    actions = None\n-    form = CustomFieldForm\n-    inlines = [CustomFieldChoiceAdmin]\n-    list_display = [\n-        \"name\",\n-        \"models\",\n-        \"type\",\n-        \"required\",\n-        \"filter_logic\",\n-        \"default\",\n-        \"weight\",\n-        \"description\",\n-    ]\n-    list_filter = [\n-        \"type\",\n-        \"required\",\n-        \"content_types\",\n-    ]\n-    fieldsets = (\n-        (\n-            \"Custom Field\",\n-            {\n-                \"fields\": (\n-                    \"type\",\n-                    \"name\",\n-                    \"weight\",\n-                    \"label\",\n-                    \"description\",\n-                    \"required\",\n-                    \"default\",\n-                    \"filter_logic\",\n-                )\n-            },\n-        ),\n-        (\n-            \"Assignment\",\n-            {\n-                \"description\": \"A custom field must be assigned to one or more object types.\",\n-                \"fields\": (\"content_types\",),\n-            },\n-        ),\n-        (\n-            \"Validation Rules\",\n-            {\n-                \"fields\": (\n-                    \"validation_minimum\",\n-                    \"validation_maximum\",\n-                    \"validation_regex\",\n-                ),\n-                \"classes\": (\"monospace\",),\n-            },\n-        ),\n-    )\n-\n-    def models(self, obj):\n-        return \", \".join([ct.name for ct in obj.content_types.all()])\n-\n-    @transaction.atomic\n-    def save_formset(self, request, form, formset, change):\n-        # TODO(John): revisit this when custom fields are moved out of admin... there is a better way...\n-        if formset.model != CustomFieldChoice:\n-            return super().save_formset(request, form, formset, change)\n-        instances = formset.save(commit=False)\n-        for instance in instances:\n-            instance.save()\n-        formset.save_m2m()\n-        for obj in formset.deleted_objects:\n-            try:\n-                obj.delete()\n-            except ProtectedError as e:\n-                self.message_user(request, e, level=messages.ERROR)\n-                raise e\n-\n-\n #\n # File attachments\n #\n", "issue": "Remove Custom Fields from Admin UI\n### Proposed Changes\r\n\r\nRemove custom fields from Admin UI. This should be as simple as deleting a bunch of code from `nautobot/extras/admin.py` that's no longer needed.\r\n\r\n### Justification\r\n\r\nNow that we have custom field management in the regular UI (#735, #997), the admin UI for custom field management is redundant.\n", "before_files": [{"content": "from db_file_storage.form_widgets import DBAdminClearableFileInput\nfrom django import forms\nfrom django.contrib import admin, messages\nfrom django.db import transaction\nfrom django.db.models import ProtectedError\n\nfrom .models import CustomField, CustomFieldChoice, FileProxy, JobResult\n\n\ndef order_content_types(field):\n    \"\"\"\n    Order the list of available ContentTypes by application\n    \"\"\"\n    queryset = field.queryset.order_by(\"app_label\", \"model\")\n    field.choices = [(ct.pk, \"{} > {}\".format(ct.app_label, ct.name)) for ct in queryset]\n\n\n#\n# Custom fields\n#\n\n\nclass CustomFieldForm(forms.ModelForm):\n    class Meta:\n        model = CustomField\n        exclude = []\n        widgets = {\n            \"default\": forms.TextInput(),\n            \"validation_regex\": forms.Textarea(\n                attrs={\n                    \"cols\": 80,\n                    \"rows\": 3,\n                }\n            ),\n        }\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n        order_content_types(self.fields[\"content_types\"])\n\n\nclass CustomFieldChoiceAdmin(admin.TabularInline):\n    \"\"\"\n    Defines the inline formset factory that handles choices for selection type custom fields.\n    The `extra` defines the default number of inline rows that appear in the UI.\n    \"\"\"\n\n    model = CustomFieldChoice\n    extra = 5\n\n\n@admin.register(CustomField)\nclass CustomFieldAdmin(admin.ModelAdmin):\n    \"\"\"\n    Define the structure and composition of the custom field form in the admin panel.\n    \"\"\"\n\n    actions = None\n    form = CustomFieldForm\n    inlines = [CustomFieldChoiceAdmin]\n    list_display = [\n        \"name\",\n        \"models\",\n        \"type\",\n        \"required\",\n        \"filter_logic\",\n        \"default\",\n        \"weight\",\n        \"description\",\n    ]\n    list_filter = [\n        \"type\",\n        \"required\",\n        \"content_types\",\n    ]\n    fieldsets = (\n        (\n            \"Custom Field\",\n            {\n                \"fields\": (\n                    \"type\",\n                    \"name\",\n                    \"weight\",\n                    \"label\",\n                    \"description\",\n                    \"required\",\n                    \"default\",\n                    \"filter_logic\",\n                )\n            },\n        ),\n        (\n            \"Assignment\",\n            {\n                \"description\": \"A custom field must be assigned to one or more object types.\",\n                \"fields\": (\"content_types\",),\n            },\n        ),\n        (\n            \"Validation Rules\",\n            {\n                \"fields\": (\n                    \"validation_minimum\",\n                    \"validation_maximum\",\n                    \"validation_regex\",\n                ),\n                \"classes\": (\"monospace\",),\n            },\n        ),\n    )\n\n    def models(self, obj):\n        return \", \".join([ct.name for ct in obj.content_types.all()])\n\n    @transaction.atomic\n    def save_formset(self, request, form, formset, change):\n        # TODO(John): revisit this when custom fields are moved out of admin... there is a better way...\n        if formset.model != CustomFieldChoice:\n            return super().save_formset(request, form, formset, change)\n        instances = formset.save(commit=False)\n        for instance in instances:\n            instance.save()\n        formset.save_m2m()\n        for obj in formset.deleted_objects:\n            try:\n                obj.delete()\n            except ProtectedError as e:\n                self.message_user(request, e, level=messages.ERROR)\n                raise e\n\n\n#\n# File attachments\n#\n\n\nclass FileProxyForm(forms.ModelForm):\n    class Meta:\n        model = FileProxy\n        exclude = []\n        widgets = {\n            \"file\": DBAdminClearableFileInput,\n        }\n\n\n@admin.register(FileProxy)\nclass FileProxyAdmin(admin.ModelAdmin):\n    form = FileProxyForm\n    list_display = [\"name\", \"uploaded_at\"]\n    list_filter = [\"uploaded_at\"]\n\n\n#\n# Job results (jobs, scripts, reports, Git repository sync, etc.)\n#\n\n\n@admin.register(JobResult)\nclass JobResultAdmin(admin.ModelAdmin):\n    list_display = [\n        \"obj_type\",\n        \"name\",\n        \"created\",\n        \"completed\",\n        \"user\",\n        \"status\",\n    ]\n    fields = [\n        \"obj_type\",\n        \"name\",\n        \"created\",\n        \"completed\",\n        \"user\",\n        \"status\",\n        \"data\",\n        \"job_id\",\n    ]\n    list_filter = [\n        \"status\",\n    ]\n    readonly_fields = fields\n\n    def has_add_permission(self, request):\n        return False\n", "path": "nautobot/extras/admin.py"}], "after_files": [{"content": "from db_file_storage.form_widgets import DBAdminClearableFileInput\nfrom django import forms\nfrom django.contrib import admin\n\nfrom .models import FileProxy, JobResult\n\n\ndef order_content_types(field):\n    \"\"\"\n    Order the list of available ContentTypes by application\n    \"\"\"\n    queryset = field.queryset.order_by(\"app_label\", \"model\")\n    field.choices = [(ct.pk, \"{} > {}\".format(ct.app_label, ct.name)) for ct in queryset]\n\n\n#\n# File attachments\n#\n\n\nclass FileProxyForm(forms.ModelForm):\n    class Meta:\n        model = FileProxy\n        exclude = []\n        widgets = {\n            \"file\": DBAdminClearableFileInput,\n        }\n\n\n@admin.register(FileProxy)\nclass FileProxyAdmin(admin.ModelAdmin):\n    form = FileProxyForm\n    list_display = [\"name\", \"uploaded_at\"]\n    list_filter = [\"uploaded_at\"]\n\n\n#\n# Job results (jobs, scripts, reports, Git repository sync, etc.)\n#\n\n\n@admin.register(JobResult)\nclass JobResultAdmin(admin.ModelAdmin):\n    list_display = [\n        \"obj_type\",\n        \"name\",\n        \"created\",\n        \"completed\",\n        \"user\",\n        \"status\",\n    ]\n    fields = [\n        \"obj_type\",\n        \"name\",\n        \"created\",\n        \"completed\",\n        \"user\",\n        \"status\",\n        \"data\",\n        \"job_id\",\n    ]\n    list_filter = [\n        \"status\",\n    ]\n    readonly_fields = fields\n\n    def has_add_permission(self, request):\n        return False\n", "path": "nautobot/extras/admin.py"}]}