models.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from django.contrib.contenttypes.fields import GenericForeignKey
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.db import models
  4. from django.urls import reverse
  5. from mptt.models import MPTTModel, TreeForeignKey
  6. from extras.utils import extras_features
  7. from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
  8. from utilities.querysets import RestrictedQuerySet
  9. from .choices import *
  10. __all__ = (
  11. 'ContactAssignment',
  12. 'Contact',
  13. 'ContactGroup',
  14. 'ContactRole',
  15. 'Tenant',
  16. 'TenantGroup',
  17. )
  18. #
  19. # Tenants
  20. #
  21. @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
  22. class TenantGroup(NestedGroupModel):
  23. """
  24. An arbitrary collection of Tenants.
  25. """
  26. name = models.CharField(
  27. max_length=100,
  28. unique=True
  29. )
  30. slug = models.SlugField(
  31. max_length=100,
  32. unique=True
  33. )
  34. parent = TreeForeignKey(
  35. to='self',
  36. on_delete=models.CASCADE,
  37. related_name='children',
  38. blank=True,
  39. null=True,
  40. db_index=True
  41. )
  42. description = models.CharField(
  43. max_length=200,
  44. blank=True
  45. )
  46. class Meta:
  47. ordering = ['name']
  48. def get_absolute_url(self):
  49. return reverse('tenancy:tenantgroup', args=[self.pk])
  50. @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
  51. class Tenant(PrimaryModel):
  52. """
  53. A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal
  54. department.
  55. """
  56. name = models.CharField(
  57. max_length=100,
  58. unique=True
  59. )
  60. slug = models.SlugField(
  61. max_length=100,
  62. unique=True
  63. )
  64. group = models.ForeignKey(
  65. to='tenancy.TenantGroup',
  66. on_delete=models.SET_NULL,
  67. related_name='tenants',
  68. blank=True,
  69. null=True
  70. )
  71. description = models.CharField(
  72. max_length=200,
  73. blank=True
  74. )
  75. comments = models.TextField(
  76. blank=True
  77. )
  78. objects = RestrictedQuerySet.as_manager()
  79. clone_fields = [
  80. 'group', 'description',
  81. ]
  82. class Meta:
  83. ordering = ['name']
  84. def __str__(self):
  85. return self.name
  86. def get_absolute_url(self):
  87. return reverse('tenancy:tenant', args=[self.pk])
  88. #
  89. # Contacts
  90. #
  91. @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
  92. class ContactGroup(NestedGroupModel):
  93. """
  94. An arbitrary collection of Contacts.
  95. """
  96. name = models.CharField(
  97. max_length=100,
  98. unique=True
  99. )
  100. slug = models.SlugField(
  101. max_length=100,
  102. unique=True
  103. )
  104. parent = TreeForeignKey(
  105. to='self',
  106. on_delete=models.CASCADE,
  107. related_name='children',
  108. blank=True,
  109. null=True,
  110. db_index=True
  111. )
  112. description = models.CharField(
  113. max_length=200,
  114. blank=True
  115. )
  116. class Meta:
  117. ordering = ['name']
  118. def get_absolute_url(self):
  119. return reverse('tenancy:contactgroup', args=[self.pk])
  120. @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
  121. class ContactRole(OrganizationalModel):
  122. """
  123. Functional role for a Contact assigned to an object.
  124. """
  125. name = models.CharField(
  126. max_length=100,
  127. unique=True
  128. )
  129. slug = models.SlugField(
  130. max_length=100,
  131. unique=True
  132. )
  133. description = models.CharField(
  134. max_length=200,
  135. blank=True,
  136. )
  137. objects = RestrictedQuerySet.as_manager()
  138. class Meta:
  139. ordering = ['name']
  140. def __str__(self):
  141. return self.name
  142. def get_absolute_url(self):
  143. return reverse('tenancy:contactrole', args=[self.pk])
  144. @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
  145. class Contact(PrimaryModel):
  146. """
  147. Contact information for a particular object(s) in NetBox.
  148. """
  149. group = models.ForeignKey(
  150. to='tenancy.ContactGroup',
  151. on_delete=models.SET_NULL,
  152. related_name='contacts',
  153. blank=True,
  154. null=True
  155. )
  156. name = models.CharField(
  157. max_length=100
  158. )
  159. title = models.CharField(
  160. max_length=100,
  161. blank=True
  162. )
  163. phone = models.CharField(
  164. max_length=50,
  165. blank=True
  166. )
  167. email = models.EmailField(
  168. blank=True
  169. )
  170. address = models.CharField(
  171. max_length=200,
  172. blank=True
  173. )
  174. comments = models.TextField(
  175. blank=True
  176. )
  177. objects = RestrictedQuerySet.as_manager()
  178. clone_fields = [
  179. 'group',
  180. ]
  181. class Meta:
  182. ordering = ['name']
  183. def __str__(self):
  184. return self.name
  185. def get_absolute_url(self):
  186. return reverse('tenancy:contact', args=[self.pk])
  187. @extras_features('webhooks')
  188. class ContactAssignment(ChangeLoggedModel):
  189. content_type = models.ForeignKey(
  190. to=ContentType,
  191. on_delete=models.CASCADE
  192. )
  193. object_id = models.PositiveIntegerField()
  194. object = GenericForeignKey(
  195. ct_field='content_type',
  196. fk_field='object_id'
  197. )
  198. contact = models.ForeignKey(
  199. to='tenancy.Contact',
  200. on_delete=models.PROTECT,
  201. related_name='assignments'
  202. )
  203. role = models.ForeignKey(
  204. to='tenancy.ContactRole',
  205. on_delete=models.PROTECT,
  206. related_name='assignments'
  207. )
  208. priority = models.CharField(
  209. max_length=50,
  210. choices=ContactPriorityChoices,
  211. blank=True
  212. )
  213. objects = RestrictedQuerySet.as_manager()
  214. class Meta:
  215. ordering = ('priority', 'contact')