forms.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. from django import forms
  2. from taggit.forms import TagField
  3. from dcim.models import Region, Site
  4. from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
  5. from tenancy.forms import TenancyFilterForm, TenancyForm
  6. from tenancy.models import Tenant
  7. from utilities.forms import (
  8. APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, DatePicker,
  9. FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField
  10. )
  11. from .constants import *
  12. from .models import Circuit, CircuitTermination, CircuitType, Provider
  13. #
  14. # Providers
  15. #
  16. class ProviderForm(BootstrapMixin, CustomFieldForm):
  17. slug = SlugField()
  18. comments = CommentField()
  19. tags = TagField(
  20. required=False
  21. )
  22. class Meta:
  23. model = Provider
  24. fields = [
  25. 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments', 'tags',
  26. ]
  27. widgets = {
  28. 'noc_contact': SmallTextarea(
  29. attrs={'rows': 5}
  30. ),
  31. 'admin_contact': SmallTextarea(
  32. attrs={'rows': 5}
  33. ),
  34. }
  35. help_texts = {
  36. 'name': "Full name of the provider",
  37. 'asn': "BGP autonomous system number (if applicable)",
  38. 'portal_url': "URL of the provider's customer support portal",
  39. 'noc_contact': "NOC email address and phone number",
  40. 'admin_contact': "Administrative contact email address and phone number",
  41. }
  42. class ProviderCSVForm(forms.ModelForm):
  43. slug = SlugField()
  44. class Meta:
  45. model = Provider
  46. fields = Provider.csv_headers
  47. help_texts = {
  48. 'name': 'Provider name',
  49. 'asn': '32-bit autonomous system number',
  50. 'portal_url': 'Portal URL',
  51. 'comments': 'Free-form comments',
  52. }
  53. class ProviderBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
  54. pk = forms.ModelMultipleChoiceField(
  55. queryset=Provider.objects.all(),
  56. widget=forms.MultipleHiddenInput
  57. )
  58. asn = forms.IntegerField(
  59. required=False,
  60. label='ASN'
  61. )
  62. account = forms.CharField(
  63. max_length=30,
  64. required=False,
  65. label='Account number'
  66. )
  67. portal_url = forms.URLField(
  68. required=False,
  69. label='Portal'
  70. )
  71. noc_contact = forms.CharField(
  72. required=False,
  73. widget=SmallTextarea,
  74. label='NOC contact'
  75. )
  76. admin_contact = forms.CharField(
  77. required=False,
  78. widget=SmallTextarea,
  79. label='Admin contact'
  80. )
  81. comments = CommentField(
  82. widget=SmallTextarea()
  83. )
  84. class Meta:
  85. nullable_fields = [
  86. 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
  87. ]
  88. class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
  89. model = Provider
  90. q = forms.CharField(
  91. required=False,
  92. label='Search'
  93. )
  94. region = FilterChoiceField(
  95. queryset=Region.objects.all(),
  96. to_field_name='slug',
  97. required=False,
  98. widget=APISelectMultiple(
  99. api_url="/api/dcim/regions/",
  100. value_field="slug",
  101. filter_for={
  102. 'site': 'region'
  103. }
  104. )
  105. )
  106. site = FilterChoiceField(
  107. queryset=Site.objects.all(),
  108. to_field_name='slug',
  109. widget=APISelectMultiple(
  110. api_url="/api/dcim/sites/",
  111. value_field="slug",
  112. )
  113. )
  114. asn = forms.IntegerField(
  115. required=False,
  116. label='ASN'
  117. )
  118. tag = TagFilterField(model)
  119. #
  120. # Circuit types
  121. #
  122. class CircuitTypeForm(BootstrapMixin, forms.ModelForm):
  123. slug = SlugField()
  124. class Meta:
  125. model = CircuitType
  126. fields = [
  127. 'name', 'slug',
  128. ]
  129. class CircuitTypeCSVForm(forms.ModelForm):
  130. slug = SlugField()
  131. class Meta:
  132. model = CircuitType
  133. fields = CircuitType.csv_headers
  134. help_texts = {
  135. 'name': 'Name of circuit type',
  136. }
  137. #
  138. # Circuits
  139. #
  140. class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
  141. comments = CommentField()
  142. tags = TagField(
  143. required=False
  144. )
  145. class Meta:
  146. model = Circuit
  147. fields = [
  148. 'cid', 'type', 'provider', 'status', 'install_date', 'commit_rate', 'description', 'tenant_group', 'tenant',
  149. 'comments', 'tags',
  150. ]
  151. help_texts = {
  152. 'cid': "Unique circuit ID",
  153. 'commit_rate': "Committed rate",
  154. }
  155. widgets = {
  156. 'provider': APISelect(
  157. api_url="/api/circuits/providers/"
  158. ),
  159. 'type': APISelect(
  160. api_url="/api/circuits/circuit-types/"
  161. ),
  162. 'status': StaticSelect2(),
  163. 'install_date': DatePicker(),
  164. }
  165. class CircuitCSVForm(forms.ModelForm):
  166. provider = forms.ModelChoiceField(
  167. queryset=Provider.objects.all(),
  168. to_field_name='name',
  169. help_text='Name of parent provider',
  170. error_messages={
  171. 'invalid_choice': 'Provider not found.'
  172. }
  173. )
  174. type = forms.ModelChoiceField(
  175. queryset=CircuitType.objects.all(),
  176. to_field_name='name',
  177. help_text='Type of circuit',
  178. error_messages={
  179. 'invalid_choice': 'Invalid circuit type.'
  180. }
  181. )
  182. status = CSVChoiceField(
  183. choices=CIRCUIT_STATUS_CHOICES,
  184. required=False,
  185. help_text='Operational status'
  186. )
  187. tenant = forms.ModelChoiceField(
  188. queryset=Tenant.objects.all(),
  189. required=False,
  190. to_field_name='name',
  191. help_text='Name of assigned tenant',
  192. error_messages={
  193. 'invalid_choice': 'Tenant not found.'
  194. }
  195. )
  196. class Meta:
  197. model = Circuit
  198. fields = [
  199. 'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
  200. ]
  201. class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
  202. pk = forms.ModelMultipleChoiceField(
  203. queryset=Circuit.objects.all(),
  204. widget=forms.MultipleHiddenInput
  205. )
  206. type = forms.ModelChoiceField(
  207. queryset=CircuitType.objects.all(),
  208. required=False,
  209. widget=APISelect(
  210. api_url="/api/circuits/circuit-types/"
  211. )
  212. )
  213. provider = forms.ModelChoiceField(
  214. queryset=Provider.objects.all(),
  215. required=False,
  216. widget=APISelect(
  217. api_url="/api/circuits/providers/"
  218. )
  219. )
  220. status = forms.ChoiceField(
  221. choices=add_blank_choice(CIRCUIT_STATUS_CHOICES),
  222. required=False,
  223. initial='',
  224. widget=StaticSelect2()
  225. )
  226. tenant = forms.ModelChoiceField(
  227. queryset=Tenant.objects.all(),
  228. required=False,
  229. widget=APISelect(
  230. api_url="/api/tenancy/tenants/"
  231. )
  232. )
  233. commit_rate = forms.IntegerField(
  234. required=False,
  235. label='Commit rate (Kbps)'
  236. )
  237. description = forms.CharField(
  238. max_length=100,
  239. required=False
  240. )
  241. comments = CommentField(
  242. widget=SmallTextarea,
  243. label='Comments'
  244. )
  245. class Meta:
  246. nullable_fields = [
  247. 'tenant', 'commit_rate', 'description', 'comments',
  248. ]
  249. class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
  250. model = Circuit
  251. field_order = [
  252. 'q', 'type', 'provider', 'status', 'region', 'site', 'tenant_group', 'tenant', 'commit_rate',
  253. ]
  254. q = forms.CharField(
  255. required=False,
  256. label='Search'
  257. )
  258. type = FilterChoiceField(
  259. queryset=CircuitType.objects.all(),
  260. to_field_name='slug',
  261. widget=APISelectMultiple(
  262. api_url="/api/circuits/circuit-types/",
  263. value_field="slug",
  264. )
  265. )
  266. provider = FilterChoiceField(
  267. queryset=Provider.objects.all(),
  268. to_field_name='slug',
  269. widget=APISelectMultiple(
  270. api_url="/api/circuits/providers/",
  271. value_field="slug",
  272. )
  273. )
  274. status = forms.MultipleChoiceField(
  275. choices=CIRCUIT_STATUS_CHOICES,
  276. required=False,
  277. widget=StaticSelect2Multiple()
  278. )
  279. region = forms.ModelMultipleChoiceField(
  280. queryset=Region.objects.all(),
  281. to_field_name='slug',
  282. required=False,
  283. widget=APISelectMultiple(
  284. api_url="/api/dcim/regions/",
  285. value_field="slug",
  286. filter_for={
  287. 'site': 'region'
  288. }
  289. )
  290. )
  291. site = FilterChoiceField(
  292. queryset=Site.objects.all(),
  293. to_field_name='slug',
  294. widget=APISelectMultiple(
  295. api_url="/api/dcim/sites/",
  296. value_field="slug",
  297. )
  298. )
  299. commit_rate = forms.IntegerField(
  300. required=False,
  301. min_value=0,
  302. label='Commit rate (Kbps)'
  303. )
  304. tag = TagFilterField(model)
  305. #
  306. # Circuit terminations
  307. #
  308. class CircuitTerminationForm(BootstrapMixin, forms.ModelForm):
  309. class Meta:
  310. model = CircuitTermination
  311. fields = [
  312. 'term_side', 'site', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description',
  313. ]
  314. help_texts = {
  315. 'port_speed': "Physical circuit speed",
  316. 'xconnect_id': "ID of the local cross-connect",
  317. 'pp_info': "Patch panel ID and port number(s)"
  318. }
  319. widgets = {
  320. 'term_side': forms.HiddenInput(),
  321. 'site': APISelect(
  322. api_url="/api/dcim/sites/"
  323. )
  324. }