Rename ContactAssignment.content_type to object_type

This commit is contained in:
Jeremy Stretch 2024-03-01 16:54:01 -05:00
parent e0165539b3
commit 5f43eabab1
12 changed files with 74 additions and 32 deletions

View File

@ -343,7 +343,9 @@ class ContactsMixin(models.Model):
Enables the assignments of Contacts (via ContactAssignment).
"""
contacts = GenericRelation(
to='tenancy.ContactAssignment'
to='tenancy.ContactAssignment',
content_type_field='object_type',
object_id_field='object_id'
)
class Meta:

View File

@ -100,7 +100,7 @@ class ContactSerializer(NetBoxModelSerializer):
class ContactAssignmentSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='tenancy-api:contactassignment-detail')
content_type = ContentTypeField(
object_type = ContentTypeField(
queryset=ContentType.objects.all()
)
object = serializers.SerializerMethodField(read_only=True)
@ -111,13 +111,13 @@ class ContactAssignmentSerializer(NetBoxModelSerializer):
class Meta:
model = ContactAssignment
fields = [
'id', 'url', 'display', 'content_type', 'object_id', 'object', 'contact', 'role', 'priority', 'tags',
'id', 'url', 'display', 'object_type', 'object_id', 'object', 'contact', 'role', 'priority', 'tags',
'custom_fields', 'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'contact', 'role', 'priority')
@extend_schema_field(OpenApiTypes.OBJECT)
def get_object(self, instance):
serializer = get_serializer_for_model(instance.content_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
serializer = get_serializer_for_model(instance.object_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
context = {'request': self.context['request']}
return serializer(instance.object, context=context).data

View File

@ -86,7 +86,7 @@ class ContactAssignmentFilterSet(NetBoxModelFilterSet):
method='search',
label=_('Search'),
)
content_type = ContentTypeFilter()
object_type = ContentTypeFilter()
contact_id = django_filters.ModelMultipleChoiceFilter(
queryset=Contact.objects.all(),
label=_('Contact (ID)'),
@ -118,7 +118,7 @@ class ContactAssignmentFilterSet(NetBoxModelFilterSet):
class Meta:
model = ContactAssignment
fields = ['id', 'content_type_id', 'object_id', 'priority', 'tag']
fields = ['id', 'object_type_id', 'object_id', 'priority', 'tag']
def search(self, queryset, name, value):
if not value.strip():

View File

@ -83,9 +83,9 @@ class ContactAssignmentFilterForm(NetBoxModelFilterSetForm):
model = ContactAssignment
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Assignment'), ('content_type_id', 'group_id', 'contact_id', 'role_id', 'priority')),
(_('Assignment'), ('object_type_id', 'group_id', 'contact_id', 'role_id', 'priority')),
)
content_type_id = ContentTypeMultipleChoiceField(
object_type_id = ContentTypeMultipleChoiceField(
queryset=ObjectType.objects.with_feature('contacts'),
required=False,
label=_('Object type')

View File

@ -143,9 +143,9 @@ class ContactAssignmentForm(NetBoxModelForm):
class Meta:
model = ContactAssignment
fields = (
'content_type', 'object_id', 'group', 'contact', 'role', 'priority', 'tags'
'object_type', 'object_id', 'group', 'contact', 'role', 'priority', 'tags'
)
widgets = {
'content_type': forms.HiddenInput(),
'object_type': forms.HiddenInput(),
'object_id': forms.HiddenInput(),
}

View File

@ -0,0 +1,40 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('extras', '0111_rename_content_types'),
('tenancy', '0014_contactassignment_ordering'),
]
operations = [
migrations.RemoveConstraint(
model_name='contactassignment',
name='tenancy_contactassignment_unique_object_contact_role',
),
migrations.RemoveIndex(
model_name='contactassignment',
name='tenancy_con_content_693ff4_idx',
),
migrations.RenameField(
model_name='contactassignment',
old_name='content_type',
new_name='object_type',
),
migrations.AddIndex(
model_name='contactassignment',
index=models.Index(
fields=['object_type', 'object_id'],
name='tenancy_con_object__6f20f7_idx'
),
),
migrations.AddConstraint(
model_name='contactassignment',
constraint=models.UniqueConstraint(
fields=('object_type', 'object_id', 'contact', 'role'),
name='tenancy_contactassignment_unique_object_contact_role'
),
),
]

View File

@ -111,13 +111,13 @@ class Contact(PrimaryModel):
class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
content_type = models.ForeignKey(
object_type = models.ForeignKey(
to='contenttypes.ContentType',
on_delete=models.CASCADE
)
object_id = models.PositiveBigIntegerField()
object = GenericForeignKey(
ct_field='content_type',
ct_field='object_type',
fk_field='object_id'
)
contact = models.ForeignKey(
@ -137,16 +137,16 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
blank=True
)
clone_fields = ('content_type', 'object_id', 'role', 'priority')
clone_fields = ('object_type', 'object_id', 'role', 'priority')
class Meta:
ordering = ('contact', 'priority', 'role', 'pk')
indexes = (
models.Index(fields=('content_type', 'object_id')),
models.Index(fields=('object_type', 'object_id')),
)
constraints = (
models.UniqueConstraint(
fields=('content_type', 'object_id', 'contact', 'role'),
fields=('object_type', 'object_id', 'contact', 'role'),
name='%(app_label)s_%(class)s_unique_object_contact_role'
),
)
@ -165,9 +165,9 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
super().clean()
# Validate the assigned object type
if self.content_type not in ObjectType.objects.with_feature('contacts'):
if self.object_type not in ObjectType.objects.with_feature('contacts'):
raise ValidationError(
_("Contacts cannot be assigned to this object type ({type}).").format(type=self.content_type)
_("Contacts cannot be assigned to this object type ({type}).").format(type=self.object_type)
)
def to_objectchange(self, action):

View File

@ -86,7 +86,7 @@ class ContactTable(NetBoxTable):
class ContactAssignmentTable(NetBoxTable):
content_type = columns.ContentTypeColumn(
object_type = columns.ContentTypeColumn(
verbose_name=_('Object Type')
)
object = tables.Column(
@ -141,10 +141,10 @@ class ContactAssignmentTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = ContactAssignment
fields = (
'pk', 'content_type', 'object', 'contact', 'role', 'priority', 'contact_title', 'contact_phone',
'pk', 'object_type', 'object', 'contact', 'role', 'priority', 'contact_title', 'contact_phone',
'contact_email', 'contact_address', 'contact_link', 'contact_description', 'contact_group', 'tags',
'actions'
)
default_columns = (
'pk', 'content_type', 'object', 'contact', 'role', 'priority', 'contact_email', 'contact_phone'
'pk', 'object_type', 'object', 'contact', 'role', 'priority', 'contact_email', 'contact_phone'
)

View File

@ -246,21 +246,21 @@ class ContactAssignmentTest(APIViewTestCases.APIViewTestCase):
cls.create_data = [
{
'content_type': 'dcim.site',
'object_type': 'dcim.site',
'object_id': sites[1].pk,
'contact': contacts[3].pk,
'role': contact_roles[0].pk,
'priority': ContactPriorityChoices.PRIORITY_PRIMARY,
},
{
'content_type': 'dcim.site',
'object_type': 'dcim.site',
'object_id': sites[1].pk,
'contact': contacts[4].pk,
'role': contact_roles[1].pk,
'priority': ContactPriorityChoices.PRIORITY_SECONDARY,
},
{
'content_type': 'dcim.site',
'object_type': 'dcim.site',
'object_id': sites[1].pk,
'contact': contacts[5].pk,
'role': contact_roles[2].pk,

View File

@ -295,8 +295,8 @@ class ContactAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests):
)
ContactAssignment.objects.bulk_create(assignments)
def test_content_type(self):
params = {'content_type_id': ContentType.objects.get_by_natural_key('dcim', 'site')}
def test_object_type(self):
params = {'object_type_id': ContentType.objects.get_by_natural_key('dcim', 'site')}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
def test_contact(self):

View File

@ -292,7 +292,7 @@ class ContactAssignmentTestCase(
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'content_type': ContentType.objects.get_for_model(Site).pk,
'object_type': ContentType.objects.get_for_model(Site).pk,
'object_id': sites[3].pk,
'contact': contacts[3].pk,
'role': contact_roles[3].pk,
@ -306,11 +306,11 @@ class ContactAssignmentTestCase(
}
def _get_url(self, action, instance=None):
# Override creation URL to append content_type & object_id parameters
# Override creation URL to append object_type & object_id parameters
if action == 'add':
url = reverse('tenancy:contactassignment_add')
content_type = ContentType.objects.get_for_model(Site).pk
object_id = Site.objects.first().pk
return f"{url}?content_type={content_type}&object_id={object_id}"
return f"{url}?object_type={content_type}&object_id={object_id}"
return super()._get_url(action, instance=instance)

View File

@ -23,7 +23,7 @@ class ObjectContactsView(generic.ObjectChildrenView):
def get_children(self, request, parent):
return ContactAssignment.objects.restrict(request.user, 'view').filter(
content_type=ContentType.objects.get_for_model(parent),
object_type=ContentType.objects.get_for_model(parent),
object_id=parent.pk
).order_by('priority', 'contact', 'role')
@ -31,7 +31,7 @@ class ObjectContactsView(generic.ObjectChildrenView):
table = super().get_table(*args, **kwargs)
# Hide object columns
table.columns.hide('content_type')
table.columns.hide('object_type')
table.columns.hide('object')
return table
@ -374,8 +374,8 @@ class ContactAssignmentEditView(generic.ObjectEditView):
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
# Assign the object based on URL kwargs
content_type = get_object_or_404(ContentType, pk=request.GET.get('content_type'))
instance.object = get_object_or_404(content_type.model_class(), pk=request.GET.get('object_id'))
object_type = get_object_or_404(ContentType, pk=request.GET.get('object_type'))
instance.object = get_object_or_404(object_type.model_class(), pk=request.GET.get('object_id'))
return instance
def get_extra_addanother_params(self, request):