Fixes #19987: Show changelog_message field only for models which support change logging
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled

This commit is contained in:
Jeremy Stretch 2025-07-31 15:58:28 -04:00
parent 128dd6e59d
commit ae425d9da9
10 changed files with 66 additions and 50 deletions

View File

@ -11,7 +11,7 @@ from ipam.choices import VLANQinQRoleChoices
from ipam.models import ASN, VLAN, VLANGroup, VRF from ipam.models import ASN, VLAN, VLANGroup, VRF
from netbox.choices import * from netbox.choices import *
from netbox.forms import NetBoxModelBulkEditForm from netbox.forms import NetBoxModelBulkEditForm
from netbox.forms.mixins import ChangeLoggingMixin from netbox.forms.mixins import ChangelogMessageMixin
from tenancy.models import Tenant from tenancy.models import Tenant
from users.models import User from users.models import User
from utilities.forms import BulkEditForm, add_blank_choice, form_from_model from utilities.forms import BulkEditForm, add_blank_choice, form_from_model
@ -1038,7 +1038,7 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
# Device component templates # Device component templates
# #
class ComponentTemplateBulkEditForm(ChangeLoggingMixin, BulkEditForm): class ComponentTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pass pass

View File

@ -11,7 +11,7 @@ from extras.models import ConfigTemplate
from ipam.choices import VLANQinQRoleChoices from ipam.choices import VLANQinQRoleChoices
from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VLANTranslationPolicy, VRF
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm
from netbox.forms.mixins import ChangeLoggingMixin from netbox.forms.mixins import ChangelogMessageMixin
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from users.models import User from users.models import User
from utilities.forms import add_blank_choice, get_field_value from utilities.forms import add_blank_choice, get_field_value
@ -974,7 +974,7 @@ class VCMemberSelectForm(forms.Form):
# Device component templates # Device component templates
# #
class ComponentTemplateForm(ChangeLoggingMixin, forms.ModelForm): class ComponentTemplateForm(ChangelogMessageMixin, forms.ModelForm):
device_type = DynamicModelChoiceField( device_type = DynamicModelChoiceField(
label=_('Device type'), label=_('Device type'),
queryset=DeviceType.objects.all(), queryset=DeviceType.objects.all(),

View File

@ -5,7 +5,7 @@ from extras.choices import *
from extras.models import * from extras.models import *
from netbox.events import get_event_type_choices from netbox.events import get_event_type_choices
from netbox.forms import NetBoxModelBulkEditForm from netbox.forms import NetBoxModelBulkEditForm
from netbox.forms.mixins import ChangeLoggingMixin from netbox.forms.mixins import ChangelogMessageMixin
from utilities.forms import BulkEditForm, add_blank_choice from utilities.forms import BulkEditForm, add_blank_choice
from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField
from utilities.forms.rendering import FieldSet from utilities.forms.rendering import FieldSet
@ -28,7 +28,7 @@ __all__ = (
) )
class CustomFieldBulkEditForm(ChangeLoggingMixin, BulkEditForm): class CustomFieldBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=CustomField.objects.all(), queryset=CustomField.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -96,7 +96,7 @@ class CustomFieldBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('group_name', 'description', 'choice_set') nullable_fields = ('group_name', 'description', 'choice_set')
class CustomFieldChoiceSetBulkEditForm(ChangeLoggingMixin, BulkEditForm): class CustomFieldChoiceSetBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=CustomFieldChoiceSet.objects.all(), queryset=CustomFieldChoiceSet.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -116,7 +116,7 @@ class CustomFieldChoiceSetBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('base_choices', 'description') nullable_fields = ('base_choices', 'description')
class CustomLinkBulkEditForm(ChangeLoggingMixin, BulkEditForm): class CustomLinkBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=CustomLink.objects.all(), queryset=CustomLink.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -142,7 +142,7 @@ class CustomLinkBulkEditForm(ChangeLoggingMixin, BulkEditForm):
) )
class ExportTemplateBulkEditForm(ChangeLoggingMixin, BulkEditForm): class ExportTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=ExportTemplate.objects.all(), queryset=ExportTemplate.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -175,7 +175,7 @@ class ExportTemplateBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension') nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension')
class SavedFilterBulkEditForm(ChangeLoggingMixin, BulkEditForm): class SavedFilterBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=SavedFilter.objects.all(), queryset=SavedFilter.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -295,7 +295,7 @@ class EventRuleBulkEditForm(NetBoxModelBulkEditForm):
nullable_fields = ('description', 'conditions') nullable_fields = ('description', 'conditions')
class TagBulkEditForm(ChangeLoggingMixin, BulkEditForm): class TagBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=Tag.objects.all(), queryset=Tag.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -317,7 +317,7 @@ class TagBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('description',) nullable_fields = ('description',)
class ConfigContextBulkEditForm(ChangeLoggingMixin, BulkEditForm): class ConfigContextBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=ConfigContext.objects.all(), queryset=ConfigContext.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -341,7 +341,7 @@ class ConfigContextBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('description',) nullable_fields = ('description',)
class ConfigTemplateBulkEditForm(ChangeLoggingMixin, BulkEditForm): class ConfigTemplateBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=ConfigTemplate.objects.all(), queryset=ConfigTemplate.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -374,7 +374,7 @@ class ConfigTemplateBulkEditForm(ChangeLoggingMixin, BulkEditForm):
nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension') nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension')
class JournalEntryBulkEditForm(ChangeLoggingMixin, BulkEditForm): class JournalEntryBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=JournalEntry.objects.all(), queryset=JournalEntry.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
@ -387,7 +387,7 @@ class JournalEntryBulkEditForm(ChangeLoggingMixin, BulkEditForm):
comments = CommentField() comments = CommentField()
class NotificationGroupBulkEditForm(ChangeLoggingMixin, BulkEditForm): class NotificationGroupBulkEditForm(ChangelogMessageMixin, BulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=NotificationGroup.objects.all(), queryset=NotificationGroup.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput

View File

@ -13,7 +13,7 @@ from extras.choices import *
from extras.models import * from extras.models import *
from netbox.events import get_event_type_choices from netbox.events import get_event_type_choices
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm
from netbox.forms.mixins import ChangeLoggingMixin from netbox.forms.mixins import ChangelogMessageMixin
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from users.models import Group, User from users.models import Group, User
from utilities.forms import get_field_value from utilities.forms import get_field_value
@ -46,7 +46,7 @@ __all__ = (
) )
class CustomFieldForm(ChangeLoggingMixin, forms.ModelForm): class CustomFieldForm(ChangelogMessageMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('custom_fields'), queryset=ObjectType.objects.with_feature('custom_fields'),
@ -165,7 +165,7 @@ class CustomFieldForm(ChangeLoggingMixin, forms.ModelForm):
del self.fields['choice_set'] del self.fields['choice_set']
class CustomFieldChoiceSetForm(ChangeLoggingMixin, forms.ModelForm): class CustomFieldChoiceSetForm(ChangelogMessageMixin, forms.ModelForm):
# TODO: The extra_choices field definition diverge from the CustomFieldChoiceSet model # TODO: The extra_choices field definition diverge from the CustomFieldChoiceSet model
extra_choices = forms.CharField( extra_choices = forms.CharField(
widget=ChoicesWidget(), widget=ChoicesWidget(),
@ -218,7 +218,7 @@ class CustomFieldChoiceSetForm(ChangeLoggingMixin, forms.ModelForm):
return data return data
class CustomLinkForm(ChangeLoggingMixin, forms.ModelForm): class CustomLinkForm(ChangelogMessageMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('custom_links') queryset=ObjectType.objects.with_feature('custom_links')
@ -250,7 +250,7 @@ class CustomLinkForm(ChangeLoggingMixin, forms.ModelForm):
} }
class ExportTemplateForm(ChangeLoggingMixin, SyncedDataMixin, forms.ModelForm): class ExportTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('export_templates') queryset=ObjectType.objects.with_feature('export_templates')
@ -292,7 +292,7 @@ class ExportTemplateForm(ChangeLoggingMixin, SyncedDataMixin, forms.ModelForm):
return self.cleaned_data return self.cleaned_data
class SavedFilterForm(ChangeLoggingMixin, forms.ModelForm): class SavedFilterForm(ChangelogMessageMixin, forms.ModelForm):
slug = SlugField() slug = SlugField()
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
@ -389,7 +389,7 @@ class BookmarkForm(forms.ModelForm):
fields = ('object_type', 'object_id') fields = ('object_type', 'object_id')
class NotificationGroupForm(ChangeLoggingMixin, forms.ModelForm): class NotificationGroupForm(ChangelogMessageMixin, forms.ModelForm):
groups = DynamicModelMultipleChoiceField( groups = DynamicModelMultipleChoiceField(
label=_('Groups'), label=_('Groups'),
required=False, required=False,
@ -562,7 +562,7 @@ class EventRuleForm(NetBoxModelForm):
return self.cleaned_data return self.cleaned_data
class TagForm(ChangeLoggingMixin, forms.ModelForm): class TagForm(ChangelogMessageMixin, forms.ModelForm):
slug = SlugField() slug = SlugField()
object_types = ContentTypeMultipleChoiceField( object_types = ContentTypeMultipleChoiceField(
label=_('Object types'), label=_('Object types'),
@ -585,7 +585,7 @@ class TagForm(ChangeLoggingMixin, forms.ModelForm):
] ]
class ConfigContextForm(ChangeLoggingMixin, SyncedDataMixin, forms.ModelForm): class ConfigContextForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
regions = DynamicModelMultipleChoiceField( regions = DynamicModelMultipleChoiceField(
label=_('Regions'), label=_('Regions'),
queryset=Region.objects.all(), queryset=Region.objects.all(),
@ -697,7 +697,7 @@ class ConfigContextForm(ChangeLoggingMixin, SyncedDataMixin, forms.ModelForm):
return self.cleaned_data return self.cleaned_data
class ConfigTemplateForm(ChangeLoggingMixin, SyncedDataMixin, forms.ModelForm): class ConfigTemplateForm(ChangelogMessageMixin, SyncedDataMixin, forms.ModelForm):
tags = DynamicModelMultipleChoiceField( tags = DynamicModelMultipleChoiceField(
label=_('Tags'), label=_('Tags'),
queryset=Tag.objects.all(), queryset=Tag.objects.all(),

View File

@ -11,7 +11,7 @@ from extras.models import CustomField, Tag
from utilities.forms import BulkEditForm, CSVModelForm from utilities.forms import BulkEditForm, CSVModelForm
from utilities.forms.fields import CSVModelMultipleChoiceField, DynamicModelMultipleChoiceField from utilities.forms.fields import CSVModelMultipleChoiceField, DynamicModelMultipleChoiceField
from utilities.forms.mixins import CheckLastUpdatedMixin from utilities.forms.mixins import CheckLastUpdatedMixin
from .mixins import ChangeLoggingMixin, CustomFieldsMixin, SavedFiltersMixin, TagsMixin from .mixins import ChangelogMessageMixin, CustomFieldsMixin, SavedFiltersMixin, TagsMixin
__all__ = ( __all__ = (
'NetBoxModelForm', 'NetBoxModelForm',
@ -21,7 +21,7 @@ __all__ = (
) )
class NetBoxModelForm(ChangeLoggingMixin, CheckLastUpdatedMixin, CustomFieldsMixin, TagsMixin, forms.ModelForm): class NetBoxModelForm(ChangelogMessageMixin, CheckLastUpdatedMixin, CustomFieldsMixin, TagsMixin, forms.ModelForm):
""" """
Base form for creating & editing NetBox models. Extends Django's ModelForm to add support for custom fields. Base form for creating & editing NetBox models. Extends Django's ModelForm to add support for custom fields.
@ -100,7 +100,7 @@ class NetBoxModelImportForm(CSVModelForm, NetBoxModelForm):
return customfield.to_form_field(for_csv_import=True) return customfield.to_form_field(for_csv_import=True)
class NetBoxModelBulkEditForm(ChangeLoggingMixin, CustomFieldsMixin, BulkEditForm): class NetBoxModelBulkEditForm(ChangelogMessageMixin, CustomFieldsMixin, BulkEditForm):
""" """
Base form for modifying multiple NetBox objects (of the same type) in bulk via the UI. Adds support for custom Base form for modifying multiple NetBox objects (of the same type) in bulk via the UI. Adds support for custom
fields and adding/removing tags. fields and adding/removing tags.

View File

@ -7,14 +7,14 @@ from extras.models import *
from utilities.forms.fields import DynamicModelMultipleChoiceField from utilities.forms.fields import DynamicModelMultipleChoiceField
__all__ = ( __all__ = (
'ChangeLoggingMixin', 'ChangelogMessageMixin',
'CustomFieldsMixin', 'CustomFieldsMixin',
'SavedFiltersMixin', 'SavedFiltersMixin',
'TagsMixin', 'TagsMixin',
) )
class ChangeLoggingMixin(forms.Form): class ChangelogMessageMixin(forms.Form):
""" """
Adds an optional field for recording a message on the resulting changelog record(s). Adds an optional field for recording a message on the resulting changelog record(s).
""" """

View File

@ -21,14 +21,12 @@ from core.models import ObjectType
from core.signals import clear_events from core.signals import clear_events
from extras.choices import CustomFieldUIEditableChoices from extras.choices import CustomFieldUIEditableChoices
from extras.models import CustomField, ExportTemplate from extras.models import CustomField, ExportTemplate
from netbox.forms.mixins import ChangeLoggingMixin
from netbox.object_actions import AddObject, BulkDelete, BulkEdit, BulkExport, BulkImport, BulkRename from netbox.object_actions import AddObject, BulkDelete, BulkEdit, BulkExport, BulkImport, BulkRename
from utilities.error_handlers import handle_protectederror from utilities.error_handlers import handle_protectederror
from utilities.exceptions import AbortRequest, AbortTransaction, PermissionsViolation from utilities.exceptions import AbortRequest, AbortTransaction, PermissionsViolation
from utilities.export import TableExport from utilities.export import TableExport
from utilities.forms import BulkRenameForm, ConfirmationForm, restrict_form_fields from utilities.forms import BulkDeleteForm, BulkRenameForm, restrict_form_fields
from utilities.forms.bulk_import import BulkImportForm from utilities.forms.bulk_import import BulkImportForm
from utilities.forms.mixins import BackgroundJobMixin
from utilities.htmx import htmx_partial from utilities.htmx import htmx_partial
from utilities.jobs import AsyncJobData, is_background_request, process_request_as_job from utilities.jobs import AsyncJobData, is_background_request, process_request_as_job
from utilities.permissions import get_permission_for_model from utilities.permissions import get_permission_for_model
@ -896,15 +894,6 @@ class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
def get_required_permission(self): def get_required_permission(self):
return get_permission_for_model(self.queryset.model, 'delete') return get_permission_for_model(self.queryset.model, 'delete')
def get_form(self):
"""
Provide a standard bulk delete form if none has been specified for the view
"""
class BulkDeleteForm(BackgroundJobMixin, ChangeLoggingMixin, ConfirmationForm):
pk = ModelMultipleChoiceField(queryset=self.queryset, widget=MultipleHiddenInput)
return BulkDeleteForm
# #
# Request handlers # Request handlers
# #
@ -925,10 +914,8 @@ class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
else: else:
pk_list = [int(pk) for pk in request.POST.getlist('pk')] pk_list = [int(pk) for pk in request.POST.getlist('pk')]
form_cls = self.get_form()
if '_confirm' in request.POST: if '_confirm' in request.POST:
form = form_cls(request.POST) form = BulkDeleteForm(model, request.POST)
if form.is_valid(): if form.is_valid():
logger.debug("Form validation was successful") logger.debug("Form validation was successful")
@ -990,7 +977,7 @@ class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
logger.debug("Form validation failed") logger.debug("Form validation failed")
else: else:
form = form_cls(initial={ form = BulkDeleteForm(model, initial={
'pk': pk_list, 'pk': pk_list,
'return_url': self.get_return_url(request), 'return_url': self.get_return_url(request),
}) })

View File

@ -425,7 +425,7 @@ class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
request: The current request request: The current request
""" """
obj = self.get_object(**kwargs) obj = self.get_object(**kwargs)
form = DeleteForm(initial=request.GET) form = DeleteForm(instance=obj, initial=request.GET)
try: try:
dependent_objects = self._get_dependent_objects(obj) dependent_objects = self._get_dependent_objects(obj)
@ -464,7 +464,7 @@ class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
""" """
logger = logging.getLogger('netbox.views.ObjectDeleteView') logger = logging.getLogger('netbox.views.ObjectDeleteView')
obj = self.get_object(**kwargs) obj = self.get_object(**kwargs)
form = DeleteForm(request.POST) form = DeleteForm(request.POST, instance=obj)
if form.is_valid(): if form.is_valid():
logger.debug("Form validation was successful") logger.debug("Form validation was successful")

View File

@ -8,13 +8,13 @@ from django.utils.translation import gettext as _
from core.forms.mixins import SyncedDataMixin from core.forms.mixins import SyncedDataMixin
from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices
from netbox.forms.mixins import ChangeLoggingMixin from netbox.forms.mixins import ChangelogMessageMixin
from utilities.constants import CSV_DELIMITERS from utilities.constants import CSV_DELIMITERS
from utilities.forms.mixins import BackgroundJobMixin from utilities.forms.mixins import BackgroundJobMixin
from utilities.forms.utils import parse_csv from utilities.forms.utils import parse_csv
class BulkImportForm(ChangeLoggingMixin, BackgroundJobMixin, SyncedDataMixin, forms.Form): class BulkImportForm(ChangelogMessageMixin, BackgroundJobMixin, SyncedDataMixin, forms.Form):
import_method = forms.ChoiceField( import_method = forms.ChoiceField(
choices=ImportMethodChoices, choices=ImportMethodChoices,
required=False required=False

View File

@ -3,9 +3,11 @@ import re
from django import forms from django import forms
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from netbox.models.features import ChangeLoggingMixin
from utilities.forms.mixins import BackgroundJobMixin from utilities.forms.mixins import BackgroundJobMixin
__all__ = ( __all__ = (
'BulkDeleteForm',
'BulkEditForm', 'BulkEditForm',
'BulkRenameForm', 'BulkRenameForm',
'ConfirmationForm', 'ConfirmationForm',
@ -40,6 +42,13 @@ class DeleteForm(ConfirmationForm):
max_length=200 max_length=200
) )
def __init__(self, *args, instance=None, **kwargs):
super().__init__(*args, **kwargs)
# Hide the changelog_message filed if the model doesn't support change logging
if instance is None or not issubclass(instance._meta.model, ChangeLoggingMixin):
self.fields.pop('changelog_message')
class BulkEditForm(BackgroundJobMixin, forms.Form): class BulkEditForm(BackgroundJobMixin, forms.Form):
""" """
@ -81,6 +90,26 @@ class BulkRenameForm(forms.Form):
}) })
class BulkDeleteForm(BackgroundJobMixin, ConfirmationForm):
pk = forms.ModelMultipleChoiceField(
queryset=None,
widget=forms.MultipleHiddenInput
)
changelog_message = forms.CharField(
required=False,
max_length=200
)
def __init__(self, model, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['pk'].queryset = model.objects.all()
# Hide the changelog_message filed if the model doesn't support change logging
if model is None or not issubclass(model, ChangeLoggingMixin):
self.fields.pop('changelog_message')
class CSVModelForm(forms.ModelForm): class CSVModelForm(forms.ModelForm):
""" """
ModelForm used for the import of objects in CSV format. ModelForm used for the import of objects in CSV format.