models.py 3.0 KB

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