forms.py 10.0 KB

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