models.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. from django.contrib.contenttypes.fields import GenericRelation
  2. from django.db import models
  3. from django.urls import reverse
  4. from mptt.models import MPTTModel, TreeForeignKey
  5. from taggit.managers import TaggableManager
  6. from extras.models import CustomFieldModel, ObjectChange, TaggedItem
  7. from extras.utils import extras_features
  8. from utilities.models import ChangeLoggedModel
  9. from utilities.utils import serialize_object
  10. __all__ = (
  11. 'Tenant',
  12. 'TenantGroup',
  13. )
  14. class TenantGroup(MPTTModel, ChangeLoggedModel):
  15. """
  16. An arbitrary collection of Tenants.
  17. """
  18. name = models.CharField(
  19. max_length=50,
  20. unique=True
  21. )
  22. slug = models.SlugField(
  23. unique=True
  24. )
  25. parent = TreeForeignKey(
  26. to='self',
  27. on_delete=models.CASCADE,
  28. related_name='children',
  29. blank=True,
  30. null=True,
  31. db_index=True
  32. )
  33. description = models.CharField(
  34. max_length=200,
  35. blank=True
  36. )
  37. csv_headers = ['name', 'slug', 'parent', 'description']
  38. class Meta:
  39. ordering = ['name']
  40. class MPTTMeta:
  41. order_insertion_by = ['name']
  42. def __str__(self):
  43. return self.name
  44. def get_absolute_url(self):
  45. return "{}?group={}".format(reverse('tenancy:tenant_list'), self.slug)
  46. def to_csv(self):
  47. return (
  48. self.name,
  49. self.slug,
  50. self.parent.name if self.parent else '',
  51. self.description,
  52. )
  53. def to_objectchange(self, action):
  54. # Remove MPTT-internal fields
  55. return ObjectChange(
  56. changed_object=self,
  57. object_repr=str(self),
  58. action=action,
  59. object_data=serialize_object(self, exclude=['level', 'lft', 'rght', 'tree_id'])
  60. )
  61. @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
  62. class Tenant(ChangeLoggedModel, CustomFieldModel):
  63. """
  64. A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal
  65. department.
  66. """
  67. name = models.CharField(
  68. max_length=30,
  69. unique=True
  70. )
  71. slug = models.SlugField(
  72. unique=True
  73. )
  74. group = models.ForeignKey(
  75. to='tenancy.TenantGroup',
  76. on_delete=models.SET_NULL,
  77. related_name='tenants',
  78. blank=True,
  79. null=True
  80. )
  81. description = models.CharField(
  82. max_length=200,
  83. blank=True
  84. )
  85. comments = models.TextField(
  86. blank=True
  87. )
  88. custom_field_values = GenericRelation(
  89. to='extras.CustomFieldValue',
  90. content_type_field='obj_type',
  91. object_id_field='obj_id'
  92. )
  93. tags = TaggableManager(through=TaggedItem)
  94. csv_headers = ['name', 'slug', 'group', 'description', 'comments']
  95. clone_fields = [
  96. 'group', 'description',
  97. ]
  98. class Meta:
  99. ordering = ['group', 'name']
  100. def __str__(self):
  101. return self.name
  102. def get_absolute_url(self):
  103. return reverse('tenancy:tenant', args=[self.slug])
  104. def to_csv(self):
  105. return (
  106. self.name,
  107. self.slug,
  108. self.group.name if self.group else None,
  109. self.description,
  110. self.comments,
  111. )