Repository: nautobot/nautobot

Issue:
Custom Fields Association with Git Repositories
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Nautobot version (Docker tag too if applicable): 1.6.8
* Python version: 3.11
* Database platform, version: postgres
* Middleware(s):

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
### Steps to Reproduce
1. Create a custom field and provide the object content type `extras | Git repository`
2. Go to edit the git repository - you cannot remove this custom field
3. All existing Git repositories now have this custom field attached
4. Add a new git repository and it will not have the custom field attached

<!-- What did you expect to happen? -->
### Expected Behavior
Custom fields should be assignable per object


<!-- What happened instead? -->
### Observed Behavior
The new custom field is applied to all existing objects.  New objects do not gain the custom field.
Editing the Git repository should allow a way to view the custom field and remove as needed.


Discussion:
Hi @mattmiller87, thank you for submitting the issue. CustomFields should applied to all objects of the ContentType you assigned it to. You can change the value of the CustomField per object but cannot dictate which object of the same ContentType gets assigned the CustomField and which does not. So that seems like expected behavior for CustomField.
I tried to recreate the issue, more specifically add a new git repository and it will not have the custom field attached on a 1.6 branch. I seem to be unable to recreate the issue. Can you attach some screenshots of what you are seeing on your Nautobot instance?
The GitRepo edit form is missing custom field form field and possibly relationship as well. We need to fix them in both 1.6 and 2.1

Resolving patch:
diff --git a/nautobot/extras/forms/forms.py b/nautobot/extras/forms/forms.py
--- a/nautobot/extras/forms/forms.py
+++ b/nautobot/extras/forms/forms.py
@@ -86,7 +86,6 @@
     CustomFieldModelFormMixin,
     NoteModelBulkEditFormMixin,
     NoteModelFormMixin,
-    RelationshipModelFormMixin,
 )
 
 
@@ -583,7 +582,7 @@ def get_context(self, name, value, attrs):
         return super().get_context(name, value, attrs)
 
 
-class GitRepositoryForm(BootstrapMixin, RelationshipModelFormMixin):
+class GitRepositoryForm(NautobotModelForm):
     slug = SlugField(help_text="Filesystem-friendly unique shorthand")
 
     remote_url = forms.URLField(


Test patch:
diff --git a/nautobot/utilities/testing/views.py b/nautobot/utilities/testing/views.py
--- a/nautobot/utilities/testing/views.py
+++ b/nautobot/utilities/testing/views.py
@@ -16,12 +16,15 @@
 from django.utils.html import escape
 from django.utils.http import urlencode
 
+from nautobot.core.models.generics import PrimaryModel
 from nautobot.extras.choices import CustomFieldTypeChoices, RelationshipSideChoices, ObjectChangeActionChoices
-from nautobot.extras.models import ChangeLoggedModel, CustomField, Relationship
+from nautobot.extras.forms.mixins import CustomFieldModelFormMixin, RelationshipModelFormMixin
+from nautobot.extras.models import ChangeLoggedModel, CustomField, CustomFieldModel, Relationship, RelationshipModel
+from nautobot.extras.models.mixins import NotesMixin
 from nautobot.users.models import ObjectPermission
 from nautobot.utilities.templatetags.helpers import bettertitle, validated_viewname
 from nautobot.utilities.testing.mixins import NautobotTestCaseMixin
-from nautobot.utilities.utils import get_changes_for_model, get_filterset_for_model, csv_format
+from nautobot.utilities.utils import get_changes_for_model, get_filterset_for_model, get_form_for_model, csv_format
 from .utils import disable_warnings, extract_page_body, get_deletable_objects, post_data
 
 
@@ -380,6 +383,20 @@ def test_create_object_with_constrained_permission(self):
                 else:
                     self.assertInstanceEqual(self._get_queryset().last(), self.form_data)
 
+        @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
+        def test_extra_feature_form_fields_present(self):
+            model_class = self.model
+            model_form = get_form_for_model(model_class)
+            fields = model_form.base_fields
+            if isinstance(model_class, CustomFieldModel):
+                self.assertTrue(issubclass(CustomFieldModelFormMixin, model_form))
+            if isinstance(model_class, RelationshipModel):
+                self.assertTrue(issubclass(RelationshipModelFormMixin, model_form))
+            if isinstance(model_class, NotesMixin):
+                self.assertIsNotNone(fields.get("object_note"))
+            if isinstance(model_class, PrimaryModel):
+                self.assertIsNotNone(fields.get("tags"))
+
         def test_slug_autocreation(self):
             """Test that slug is autocreated through ORM."""
             # This really should go on a models test page, but we don't have test structures for models.