model_forms.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.core.exceptions import ObjectDoesNotExist
  3. from django.utils.translation import gettext_lazy as _
  4. from circuits.choices import CircuitCommitRateChoices, CircuitTerminationPortSpeedChoices
  5. from circuits.constants import *
  6. from circuits.models import *
  7. from dcim.models import Site
  8. from ipam.models import ASN
  9. from netbox.forms import NetBoxModelForm
  10. from tenancy.forms import TenancyForm
  11. from utilities.forms import get_field_value
  12. from utilities.forms.fields import CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField
  13. from utilities.forms.rendering import FieldSet, InlineFields
  14. from utilities.forms.widgets import DatePicker, HTMXSelect, NumberWithOptions
  15. from utilities.templatetags.builtins.filters import bettertitle
  16. __all__ = (
  17. 'CircuitForm',
  18. 'CircuitGroupAssignmentForm',
  19. 'CircuitGroupForm',
  20. 'CircuitTerminationForm',
  21. 'CircuitTypeForm',
  22. 'ProviderForm',
  23. 'ProviderAccountForm',
  24. 'ProviderNetworkForm',
  25. )
  26. class ProviderForm(NetBoxModelForm):
  27. slug = SlugField()
  28. asns = DynamicModelMultipleChoiceField(
  29. queryset=ASN.objects.all(),
  30. label=_('ASNs'),
  31. required=False
  32. )
  33. comments = CommentField()
  34. fieldsets = (
  35. FieldSet('name', 'slug', 'asns', 'description', 'tags'),
  36. )
  37. class Meta:
  38. model = Provider
  39. fields = [
  40. 'name', 'slug', 'asns', 'description', 'comments', 'tags',
  41. ]
  42. class ProviderAccountForm(NetBoxModelForm):
  43. provider = DynamicModelChoiceField(
  44. label=_('Provider'),
  45. queryset=Provider.objects.all()
  46. )
  47. comments = CommentField()
  48. class Meta:
  49. model = ProviderAccount
  50. fields = [
  51. 'provider', 'name', 'account', 'description', 'comments', 'tags',
  52. ]
  53. class ProviderNetworkForm(NetBoxModelForm):
  54. provider = DynamicModelChoiceField(
  55. label=_('Provider'),
  56. queryset=Provider.objects.all()
  57. )
  58. comments = CommentField()
  59. fieldsets = (
  60. FieldSet('provider', 'name', 'service_id', 'description', 'tags'),
  61. )
  62. class Meta:
  63. model = ProviderNetwork
  64. fields = [
  65. 'provider', 'name', 'service_id', 'description', 'comments', 'tags',
  66. ]
  67. class CircuitTypeForm(NetBoxModelForm):
  68. slug = SlugField()
  69. fieldsets = (
  70. FieldSet('name', 'slug', 'color', 'description', 'tags'),
  71. )
  72. class Meta:
  73. model = CircuitType
  74. fields = [
  75. 'name', 'slug', 'color', 'description', 'tags',
  76. ]
  77. class CircuitForm(TenancyForm, NetBoxModelForm):
  78. provider = DynamicModelChoiceField(
  79. label=_('Provider'),
  80. queryset=Provider.objects.all(),
  81. selector=True
  82. )
  83. provider_account = DynamicModelChoiceField(
  84. label=_('Provider account'),
  85. queryset=ProviderAccount.objects.all(),
  86. required=False,
  87. query_params={
  88. 'provider_id': '$provider',
  89. }
  90. )
  91. type = DynamicModelChoiceField(
  92. queryset=CircuitType.objects.all()
  93. )
  94. comments = CommentField()
  95. fieldsets = (
  96. FieldSet(
  97. 'provider',
  98. 'provider_account',
  99. 'cid',
  100. 'type',
  101. 'status',
  102. InlineFields('distance', 'distance_unit', label=_('Distance')),
  103. 'description',
  104. 'tags',
  105. name=_('Circuit')
  106. ),
  107. FieldSet('install_date', 'termination_date', 'commit_rate', name=_('Service Parameters')),
  108. FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
  109. )
  110. class Meta:
  111. model = Circuit
  112. fields = [
  113. 'cid', 'type', 'provider', 'provider_account', 'status', 'install_date', 'termination_date', 'commit_rate',
  114. 'distance', 'distance_unit', 'description', 'tenant_group', 'tenant', 'comments', 'tags',
  115. ]
  116. widgets = {
  117. 'install_date': DatePicker(),
  118. 'termination_date': DatePicker(),
  119. 'commit_rate': NumberWithOptions(
  120. options=CircuitCommitRateChoices
  121. ),
  122. }
  123. class CircuitTerminationForm(NetBoxModelForm):
  124. circuit = DynamicModelChoiceField(
  125. label=_('Circuit'),
  126. queryset=Circuit.objects.all(),
  127. selector=True
  128. )
  129. termination_type = ContentTypeChoiceField(
  130. queryset=ContentType.objects.filter(model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES),
  131. widget=HTMXSelect(),
  132. required=False,
  133. label=_('Termination type')
  134. )
  135. termination = DynamicModelChoiceField(
  136. label=_('Termination'),
  137. queryset=Site.objects.none(), # Initial queryset
  138. required=False,
  139. disabled=True,
  140. selector=True
  141. )
  142. fieldsets = (
  143. FieldSet(
  144. 'circuit', 'term_side', 'description', 'tags',
  145. 'termination_type', 'termination',
  146. 'mark_connected', name=_('Circuit Termination')
  147. ),
  148. FieldSet('port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', name=_('Termination Details')),
  149. )
  150. class Meta:
  151. model = CircuitTermination
  152. fields = [
  153. 'circuit', 'term_side', 'termination_type', 'mark_connected', 'port_speed', 'upstream_speed',
  154. 'xconnect_id', 'pp_info', 'description', 'tags',
  155. ]
  156. widgets = {
  157. 'port_speed': NumberWithOptions(
  158. options=CircuitTerminationPortSpeedChoices
  159. ),
  160. 'upstream_speed': NumberWithOptions(
  161. options=CircuitTerminationPortSpeedChoices
  162. ),
  163. }
  164. def __init__(self, *args, **kwargs):
  165. instance = kwargs.get('instance')
  166. initial = kwargs.get('initial', {})
  167. if instance is not None and instance.termination:
  168. initial['termination'] = instance.termination
  169. kwargs['initial'] = initial
  170. super().__init__(*args, **kwargs)
  171. if termination_type_id := get_field_value(self, 'termination_type'):
  172. try:
  173. termination_type = ContentType.objects.get(pk=termination_type_id)
  174. model = termination_type.model_class()
  175. self.fields['termination'].queryset = model.objects.all()
  176. self.fields['termination'].widget.attrs['selector'] = model._meta.label_lower
  177. self.fields['termination'].disabled = False
  178. self.fields['termination'].label = _(bettertitle(model._meta.verbose_name))
  179. except ObjectDoesNotExist:
  180. pass
  181. if self.instance and termination_type_id != self.instance.termination_type_id:
  182. self.initial['termination'] = None
  183. def clean(self):
  184. super().clean()
  185. # Assign the selected termination (if any)
  186. self.instance.termination = self.cleaned_data.get('termination')
  187. class CircuitGroupForm(TenancyForm, NetBoxModelForm):
  188. slug = SlugField()
  189. fieldsets = (
  190. FieldSet('name', 'slug', 'description', 'tags', name=_('Circuit Group')),
  191. FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
  192. )
  193. class Meta:
  194. model = CircuitGroup
  195. fields = [
  196. 'name', 'slug', 'description', 'tenant_group', 'tenant', 'tags',
  197. ]
  198. class CircuitGroupAssignmentForm(NetBoxModelForm):
  199. group = DynamicModelChoiceField(
  200. label=_('Group'),
  201. queryset=CircuitGroup.objects.all(),
  202. )
  203. circuit = DynamicModelChoiceField(
  204. label=_('Circuit'),
  205. queryset=Circuit.objects.all(),
  206. selector=True
  207. )
  208. class Meta:
  209. model = CircuitGroupAssignment
  210. fields = [
  211. 'group', 'circuit', 'priority', 'tags',
  212. ]