views.py 137 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135
  1. from django.contrib import messages
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.core.paginator import EmptyPage, PageNotAnInteger
  4. from django.db import transaction
  5. from django.db.models import Prefetch
  6. from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory
  7. from django.shortcuts import get_object_or_404, redirect, render
  8. from django.urls import reverse
  9. from django.utils.html import escape
  10. from django.utils.safestring import mark_safe
  11. from django.utils.translation import gettext_lazy as _
  12. from django.views.generic import View
  13. from circuits.models import Circuit, CircuitTermination
  14. from extras.views import ObjectConfigContextView, ObjectRenderConfigView
  15. from ipam.models import ASN, IPAddress, Prefix, VLANGroup, VLAN
  16. from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
  17. from netbox.constants import DEFAULT_ACTION_PERMISSIONS
  18. from netbox.views import generic
  19. from utilities.forms import ConfirmationForm
  20. from utilities.paginator import EnhancedPaginator, get_paginate_count
  21. from utilities.permissions import get_permission_for_model
  22. from utilities.query import count_related
  23. from utilities.query_functions import CollateAsChar
  24. from utilities.views import (
  25. GetRelatedModelsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view
  26. )
  27. from virtualization.filtersets import VirtualMachineFilterSet
  28. from virtualization.forms import VirtualMachineFilterForm
  29. from virtualization.models import Cluster, VirtualMachine
  30. from virtualization.tables import VirtualMachineTable
  31. from wireless.models import WirelessLAN
  32. from . import filtersets, forms, tables
  33. from .choices import DeviceFaceChoices, InterfaceModeChoices
  34. from .models import *
  35. CABLE_TERMINATION_TYPES = {
  36. 'dcim.consoleport': ConsolePort,
  37. 'dcim.consoleserverport': ConsoleServerPort,
  38. 'dcim.powerport': PowerPort,
  39. 'dcim.poweroutlet': PowerOutlet,
  40. 'dcim.interface': Interface,
  41. 'dcim.frontport': FrontPort,
  42. 'dcim.rearport': RearPort,
  43. 'dcim.powerfeed': PowerFeed,
  44. 'circuits.circuittermination': CircuitTermination,
  45. }
  46. class DeviceComponentsView(generic.ObjectChildrenView):
  47. actions = {
  48. **DEFAULT_ACTION_PERMISSIONS,
  49. 'bulk_rename': {'change'},
  50. 'bulk_disconnect': {'change'},
  51. }
  52. queryset = Device.objects.all()
  53. def get_children(self, request, parent):
  54. return self.child_model.objects.restrict(request.user, 'view').filter(device=parent)
  55. class DeviceTypeComponentsView(generic.ObjectChildrenView):
  56. actions = {
  57. **DEFAULT_ACTION_PERMISSIONS,
  58. 'bulk_rename': {'change'},
  59. }
  60. queryset = DeviceType.objects.all()
  61. template_name = 'dcim/devicetype/component_templates.html'
  62. viewname = None # Used for return_url resolution
  63. def get_children(self, request, parent):
  64. return self.child_model.objects.restrict(request.user, 'view').filter(device_type=parent)
  65. def get_extra_context(self, request, instance):
  66. return {
  67. 'return_url': reverse(self.viewname, kwargs={'pk': instance.pk}),
  68. }
  69. class ModuleTypeComponentsView(DeviceComponentsView):
  70. queryset = ModuleType.objects.all()
  71. template_name = 'dcim/moduletype/component_templates.html'
  72. viewname = None # Used for return_url resolution
  73. def get_children(self, request, parent):
  74. return self.child_model.objects.restrict(request.user, 'view').filter(module_type=parent)
  75. def get_extra_context(self, request, instance):
  76. return {
  77. 'return_url': reverse(self.viewname, kwargs={'pk': instance.pk}),
  78. }
  79. class BulkDisconnectView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
  80. """
  81. An extendable view for disconnection console/power/interface components in bulk.
  82. """
  83. queryset = None
  84. template_name = 'dcim/bulk_disconnect.html'
  85. def __init__(self, *args, **kwargs):
  86. super().__init__(*args, **kwargs)
  87. # Create a new Form class from ConfirmationForm
  88. class _Form(ConfirmationForm):
  89. pk = ModelMultipleChoiceField(
  90. queryset=self.queryset,
  91. widget=MultipleHiddenInput()
  92. )
  93. self.form = _Form
  94. def get_required_permission(self):
  95. return get_permission_for_model(self.queryset.model, 'change')
  96. def post(self, request):
  97. selected_objects = []
  98. return_url = self.get_return_url(request)
  99. if '_confirm' in request.POST:
  100. form = self.form(request.POST)
  101. if form.is_valid():
  102. with transaction.atomic():
  103. count = 0
  104. cable_ids = set()
  105. for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']):
  106. if obj.cable:
  107. cable_ids.add(obj.cable.pk)
  108. count += 1
  109. for cable in Cable.objects.filter(pk__in=cable_ids):
  110. cable.delete()
  111. messages.success(request, _("Disconnected {count} {type}").format(
  112. count=count,
  113. type=self.queryset.model._meta.verbose_name_plural
  114. ))
  115. return redirect(return_url)
  116. else:
  117. form = self.form(initial={'pk': request.POST.getlist('pk')})
  118. selected_objects = self.queryset.filter(pk__in=form.initial['pk'])
  119. return render(request, self.template_name, {
  120. 'form': form,
  121. 'obj_type_plural': self.queryset.model._meta.verbose_name_plural,
  122. 'selected_objects': selected_objects,
  123. 'return_url': return_url,
  124. })
  125. class PathTraceView(generic.ObjectView):
  126. """
  127. Trace a cable path beginning from the given path endpoint (origin).
  128. """
  129. additional_permissions = ['dcim.view_cable']
  130. template_name = 'dcim/cable_trace.html'
  131. def dispatch(self, request, *args, **kwargs):
  132. model = kwargs.pop('model')
  133. self.queryset = model.objects.all()
  134. return super().dispatch(request, *args, **kwargs)
  135. def get_extra_context(self, request, instance):
  136. related_paths = []
  137. # If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin
  138. if isinstance(instance, PathEndpoint):
  139. path = instance._path
  140. # Otherwise, find all CablePaths which traverse the specified object
  141. else:
  142. related_paths = CablePath.objects.filter(_nodes__contains=instance)
  143. # Check for specification of a particular path (when tracing pass-through ports)
  144. try:
  145. path_id = int(request.GET.get('cablepath_id'))
  146. except TypeError:
  147. path_id = None
  148. if path_id in list(related_paths.values_list('pk', flat=True)):
  149. path = CablePath.objects.get(pk=path_id)
  150. else:
  151. path = related_paths.first()
  152. # No paths found
  153. if path is None:
  154. return {
  155. 'path': None
  156. }
  157. # Get the total length of the cable and whether the length is definitive (fully defined)
  158. total_length, is_definitive = path.get_total_length() if path else (None, False)
  159. # Determine the path to the SVG trace image
  160. api_viewname = f"{path.origin_type.app_label}-api:{path.origin_type.model}-trace"
  161. svg_url = f"{reverse(api_viewname, kwargs={'pk': path.origins[0].pk})}?render=svg"
  162. return {
  163. 'path': path,
  164. 'related_paths': related_paths,
  165. 'total_length': total_length,
  166. 'is_definitive': is_definitive,
  167. 'svg_url': svg_url,
  168. }
  169. #
  170. # Regions
  171. #
  172. @register_model_view(Region, 'list', path='', detail=False)
  173. class RegionListView(generic.ObjectListView):
  174. queryset = Region.objects.add_related_count(
  175. Region.objects.all(),
  176. Site,
  177. 'region',
  178. 'site_count',
  179. cumulative=True
  180. )
  181. filterset = filtersets.RegionFilterSet
  182. filterset_form = forms.RegionFilterForm
  183. table = tables.RegionTable
  184. @register_model_view(Region)
  185. class RegionView(GetRelatedModelsMixin, generic.ObjectView):
  186. queryset = Region.objects.all()
  187. def get_extra_context(self, request, instance):
  188. regions = instance.get_descendants(include_self=True)
  189. return {
  190. 'related_models': self.get_related_models(
  191. request,
  192. regions,
  193. omit=(Cluster, CircuitTermination, Prefix, WirelessLAN),
  194. extra=(
  195. (Location.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'),
  196. (Rack.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'),
  197. (
  198. Circuit.objects.restrict(request.user, 'view').filter(
  199. terminations___region=instance
  200. ).distinct(),
  201. 'region_id'
  202. ),
  203. (
  204. VLANGroup.objects.restrict(request.user, 'view').filter(
  205. scope_type=ContentType.objects.get_for_model(Region),
  206. scope_id__in=regions
  207. ).distinct(),
  208. 'region'
  209. ),
  210. # Handle these relations manually to avoid erroneous filter name resolution
  211. (
  212. CircuitTermination.objects.restrict(request.user, 'view').filter(_region__in=regions),
  213. 'region_id'
  214. ),
  215. (Cluster.objects.restrict(request.user, 'view').filter(_region__in=regions), 'region_id'),
  216. (Prefix.objects.restrict(request.user, 'view').filter(_region__in=regions), 'region_id'),
  217. (WirelessLAN.objects.restrict(request.user, 'view').filter(_region__in=regions), 'region_id'),
  218. ),
  219. ),
  220. }
  221. @register_model_view(Region, 'add', detail=False)
  222. @register_model_view(Region, 'edit')
  223. class RegionEditView(generic.ObjectEditView):
  224. queryset = Region.objects.all()
  225. form = forms.RegionForm
  226. @register_model_view(Region, 'delete')
  227. class RegionDeleteView(generic.ObjectDeleteView):
  228. queryset = Region.objects.all()
  229. @register_model_view(Region, 'bulk_import', detail=False)
  230. class RegionBulkImportView(generic.BulkImportView):
  231. queryset = Region.objects.all()
  232. model_form = forms.RegionImportForm
  233. @register_model_view(Region, 'bulk_edit', path='edit', detail=False)
  234. class RegionBulkEditView(generic.BulkEditView):
  235. queryset = Region.objects.add_related_count(
  236. Region.objects.all(),
  237. Site,
  238. 'region',
  239. 'site_count',
  240. cumulative=True
  241. )
  242. filterset = filtersets.RegionFilterSet
  243. table = tables.RegionTable
  244. form = forms.RegionBulkEditForm
  245. @register_model_view(Region, 'bulk_delete', path='delete', detail=False)
  246. class RegionBulkDeleteView(generic.BulkDeleteView):
  247. queryset = Region.objects.add_related_count(
  248. Region.objects.all(),
  249. Site,
  250. 'region',
  251. 'site_count',
  252. cumulative=True
  253. )
  254. filterset = filtersets.RegionFilterSet
  255. table = tables.RegionTable
  256. #
  257. # Site groups
  258. #
  259. @register_model_view(SiteGroup, 'list', path='', detail=False)
  260. class SiteGroupListView(generic.ObjectListView):
  261. queryset = SiteGroup.objects.add_related_count(
  262. SiteGroup.objects.all(),
  263. Site,
  264. 'group',
  265. 'site_count',
  266. cumulative=True
  267. )
  268. filterset = filtersets.SiteGroupFilterSet
  269. filterset_form = forms.SiteGroupFilterForm
  270. table = tables.SiteGroupTable
  271. @register_model_view(SiteGroup)
  272. class SiteGroupView(GetRelatedModelsMixin, generic.ObjectView):
  273. queryset = SiteGroup.objects.all()
  274. def get_extra_context(self, request, instance):
  275. groups = instance.get_descendants(include_self=True)
  276. return {
  277. 'related_models': self.get_related_models(
  278. request,
  279. groups,
  280. omit=(Cluster, CircuitTermination, Prefix, WirelessLAN),
  281. extra=(
  282. (Location.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'),
  283. (Rack.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'),
  284. (Device.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'),
  285. (VLAN.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'),
  286. (
  287. ASN.objects.restrict(request.user, 'view').filter(
  288. sites__group__in=groups
  289. ).distinct(),
  290. 'site_group_id'),
  291. (
  292. VirtualMachine.objects.restrict(request.user, 'view').filter(
  293. site__group__in=groups),
  294. 'site_group_id'
  295. ),
  296. (
  297. VLANGroup.objects.restrict(request.user, 'view').filter(
  298. scope_type=ContentType.objects.get_for_model(SiteGroup),
  299. scope_id__in=groups
  300. ).distinct(),
  301. 'site_group'
  302. ),
  303. (
  304. Circuit.objects.restrict(request.user, 'view').filter(
  305. terminations___site_group=instance
  306. ).distinct(),
  307. 'site_group_id'
  308. ),
  309. # Handle these relations manually to avoid erroneous filter name resolution
  310. (
  311. CircuitTermination.objects.restrict(request.user, 'view').filter(_site_group__in=groups),
  312. 'site_group_id'
  313. ),
  314. (
  315. Cluster.objects.restrict(request.user, 'view').filter(_site_group__in=groups),
  316. 'site_group_id'
  317. ),
  318. (
  319. Prefix.objects.restrict(request.user, 'view').filter(_site_group__in=groups),
  320. 'site_group_id'
  321. ),
  322. (
  323. WirelessLAN.objects.restrict(request.user, 'view').filter(_site_group__in=groups),
  324. 'site_group_id'
  325. ),
  326. ),
  327. ),
  328. }
  329. @register_model_view(SiteGroup, 'add', detail=False)
  330. @register_model_view(SiteGroup, 'edit')
  331. class SiteGroupEditView(generic.ObjectEditView):
  332. queryset = SiteGroup.objects.all()
  333. form = forms.SiteGroupForm
  334. @register_model_view(SiteGroup, 'delete')
  335. class SiteGroupDeleteView(generic.ObjectDeleteView):
  336. queryset = SiteGroup.objects.all()
  337. @register_model_view(SiteGroup, 'bulk_import', detail=False)
  338. class SiteGroupBulkImportView(generic.BulkImportView):
  339. queryset = SiteGroup.objects.all()
  340. model_form = forms.SiteGroupImportForm
  341. @register_model_view(SiteGroup, 'bulk_edit', path='edit', detail=False)
  342. class SiteGroupBulkEditView(generic.BulkEditView):
  343. queryset = SiteGroup.objects.add_related_count(
  344. SiteGroup.objects.all(),
  345. Site,
  346. 'group',
  347. 'site_count',
  348. cumulative=True
  349. )
  350. filterset = filtersets.SiteGroupFilterSet
  351. table = tables.SiteGroupTable
  352. form = forms.SiteGroupBulkEditForm
  353. @register_model_view(SiteGroup, 'bulk_delete', path='delete', detail=False)
  354. class SiteGroupBulkDeleteView(generic.BulkDeleteView):
  355. queryset = SiteGroup.objects.add_related_count(
  356. SiteGroup.objects.all(),
  357. Site,
  358. 'group',
  359. 'site_count',
  360. cumulative=True
  361. )
  362. filterset = filtersets.SiteGroupFilterSet
  363. table = tables.SiteGroupTable
  364. #
  365. # Sites
  366. #
  367. @register_model_view(Site, 'list', path='', detail=False)
  368. class SiteListView(generic.ObjectListView):
  369. queryset = Site.objects.annotate(
  370. device_count=count_related(Device, 'site'),
  371. asn_count=count_related(ASN, 'sites')
  372. )
  373. filterset = filtersets.SiteFilterSet
  374. filterset_form = forms.SiteFilterForm
  375. table = tables.SiteTable
  376. @register_model_view(Site)
  377. class SiteView(GetRelatedModelsMixin, generic.ObjectView):
  378. queryset = Site.objects.prefetch_related('tenant__group')
  379. def get_extra_context(self, request, instance):
  380. return {
  381. 'related_models': self.get_related_models(
  382. request,
  383. instance,
  384. omit=(CableTermination, CircuitTermination, Cluster, Prefix, WirelessLAN),
  385. extra=(
  386. (VLANGroup.objects.restrict(request.user, 'view').filter(
  387. scope_type=ContentType.objects.get_for_model(Site),
  388. scope_id=instance.pk
  389. ), 'site'),
  390. (ASN.objects.restrict(request.user, 'view').filter(sites=instance), 'site_id'),
  391. (
  392. Circuit.objects.restrict(request.user, 'view').filter(terminations___site=instance).distinct(),
  393. 'site_id'
  394. ),
  395. # Handle these relations manually to avoid erroneous filter name resolution
  396. (Cluster.objects.restrict(request.user, 'view').filter(_site=instance), 'site_id'),
  397. (Prefix.objects.restrict(request.user, 'view').filter(_site=instance), 'site_id'),
  398. (WirelessLAN.objects.restrict(request.user, 'view').filter(_site=instance), 'site_id'),
  399. (CircuitTermination.objects.restrict(request.user, 'view').filter(_site=instance), 'site_id'),
  400. ),
  401. ),
  402. }
  403. @register_model_view(Site, 'add', detail=False)
  404. @register_model_view(Site, 'edit')
  405. class SiteEditView(generic.ObjectEditView):
  406. queryset = Site.objects.all()
  407. form = forms.SiteForm
  408. @register_model_view(Site, 'delete')
  409. class SiteDeleteView(generic.ObjectDeleteView):
  410. queryset = Site.objects.all()
  411. @register_model_view(Site, 'bulk_import', detail=False)
  412. class SiteBulkImportView(generic.BulkImportView):
  413. queryset = Site.objects.all()
  414. model_form = forms.SiteImportForm
  415. @register_model_view(Site, 'bulk_edit', path='edit', detail=False)
  416. class SiteBulkEditView(generic.BulkEditView):
  417. queryset = Site.objects.all()
  418. filterset = filtersets.SiteFilterSet
  419. table = tables.SiteTable
  420. form = forms.SiteBulkEditForm
  421. @register_model_view(Site, 'bulk_delete', path='delete', detail=False)
  422. class SiteBulkDeleteView(generic.BulkDeleteView):
  423. queryset = Site.objects.all()
  424. filterset = filtersets.SiteFilterSet
  425. table = tables.SiteTable
  426. #
  427. # Locations
  428. #
  429. @register_model_view(Location, 'list', path='', detail=False)
  430. class LocationListView(generic.ObjectListView):
  431. queryset = Location.objects.add_related_count(
  432. Location.objects.add_related_count(
  433. Location.objects.add_related_count(
  434. Location.objects.all(),
  435. Device,
  436. 'location',
  437. 'device_count',
  438. cumulative=True
  439. ),
  440. Rack,
  441. 'location',
  442. 'rack_count',
  443. cumulative=True
  444. ),
  445. VLANGroup,
  446. 'location',
  447. 'vlangroup_count',
  448. cumulative=True
  449. )
  450. filterset = filtersets.LocationFilterSet
  451. filterset_form = forms.LocationFilterForm
  452. table = tables.LocationTable
  453. @register_model_view(Location)
  454. class LocationView(GetRelatedModelsMixin, generic.ObjectView):
  455. queryset = Location.objects.all()
  456. def get_extra_context(self, request, instance):
  457. locations = instance.get_descendants(include_self=True)
  458. location_content_type = ContentType.objects.get_for_model(instance)
  459. return {
  460. 'related_models': self.get_related_models(
  461. request,
  462. locations,
  463. omit=[CableTermination, CircuitTermination, Cluster, Prefix, WirelessLAN],
  464. extra=(
  465. (
  466. Circuit.objects.restrict(request.user, 'view').filter(
  467. terminations___location=instance
  468. ).distinct(),
  469. 'location_id'
  470. ),
  471. # Handle these relations manually to avoid erroneous filter name resolution
  472. (
  473. CircuitTermination.objects.restrict(request.user, 'view').filter(_location=instance),
  474. 'location_id'
  475. ),
  476. (Cluster.objects.restrict(request.user, 'view').filter(_location=instance), 'location_id'),
  477. (Prefix.objects.restrict(request.user, 'view').filter(_location=instance), 'location_id'),
  478. (WirelessLAN.objects.restrict(request.user, 'view').filter(_location=instance), 'location_id'),
  479. (VLANGroup.objects.restrict(request.user, 'view').filter(
  480. scope_type_id=location_content_type.id, scope_id=instance.id), 'location'),
  481. ),
  482. ),
  483. }
  484. @register_model_view(Location, 'add', detail=False)
  485. @register_model_view(Location, 'edit')
  486. class LocationEditView(generic.ObjectEditView):
  487. queryset = Location.objects.all()
  488. form = forms.LocationForm
  489. @register_model_view(Location, 'delete')
  490. class LocationDeleteView(generic.ObjectDeleteView):
  491. queryset = Location.objects.all()
  492. @register_model_view(Location, 'bulk_import', detail=False)
  493. class LocationBulkImportView(generic.BulkImportView):
  494. queryset = Location.objects.all()
  495. model_form = forms.LocationImportForm
  496. @register_model_view(Location, 'bulk_edit', path='edit', detail=False)
  497. class LocationBulkEditView(generic.BulkEditView):
  498. queryset = Location.objects.add_related_count(
  499. Location.objects.all(),
  500. Rack,
  501. 'location',
  502. 'rack_count',
  503. cumulative=True
  504. ).prefetch_related('site')
  505. filterset = filtersets.LocationFilterSet
  506. table = tables.LocationTable
  507. form = forms.LocationBulkEditForm
  508. @register_model_view(Location, 'bulk_delete', path='delete', detail=False)
  509. class LocationBulkDeleteView(generic.BulkDeleteView):
  510. queryset = Location.objects.add_related_count(
  511. Location.objects.all(),
  512. Rack,
  513. 'location',
  514. 'rack_count',
  515. cumulative=True
  516. ).prefetch_related('site')
  517. filterset = filtersets.LocationFilterSet
  518. table = tables.LocationTable
  519. #
  520. # Rack roles
  521. #
  522. @register_model_view(RackRole, 'list', path='', detail=False)
  523. class RackRoleListView(generic.ObjectListView):
  524. queryset = RackRole.objects.annotate(
  525. rack_count=count_related(Rack, 'role')
  526. )
  527. filterset = filtersets.RackRoleFilterSet
  528. filterset_form = forms.RackRoleFilterForm
  529. table = tables.RackRoleTable
  530. @register_model_view(RackRole)
  531. class RackRoleView(GetRelatedModelsMixin, generic.ObjectView):
  532. queryset = RackRole.objects.all()
  533. def get_extra_context(self, request, instance):
  534. return {
  535. 'related_models': self.get_related_models(request, instance),
  536. }
  537. @register_model_view(RackRole, 'add', detail=False)
  538. @register_model_view(RackRole, 'edit')
  539. class RackRoleEditView(generic.ObjectEditView):
  540. queryset = RackRole.objects.all()
  541. form = forms.RackRoleForm
  542. @register_model_view(RackRole, 'delete')
  543. class RackRoleDeleteView(generic.ObjectDeleteView):
  544. queryset = RackRole.objects.all()
  545. @register_model_view(RackRole, 'bulk_import', detail=False)
  546. class RackRoleBulkImportView(generic.BulkImportView):
  547. queryset = RackRole.objects.all()
  548. model_form = forms.RackRoleImportForm
  549. @register_model_view(RackRole, 'bulk_edit', path='edit', detail=False)
  550. class RackRoleBulkEditView(generic.BulkEditView):
  551. queryset = RackRole.objects.annotate(
  552. rack_count=count_related(Rack, 'role')
  553. )
  554. filterset = filtersets.RackRoleFilterSet
  555. table = tables.RackRoleTable
  556. form = forms.RackRoleBulkEditForm
  557. @register_model_view(RackRole, 'bulk_delete', path='delete', detail=False)
  558. class RackRoleBulkDeleteView(generic.BulkDeleteView):
  559. queryset = RackRole.objects.annotate(
  560. rack_count=count_related(Rack, 'role')
  561. )
  562. filterset = filtersets.RackRoleFilterSet
  563. table = tables.RackRoleTable
  564. #
  565. # RackTypes
  566. #
  567. @register_model_view(RackType, 'list', path='', detail=False)
  568. class RackTypeListView(generic.ObjectListView):
  569. queryset = RackType.objects.annotate(
  570. instance_count=count_related(Rack, 'rack_type')
  571. )
  572. filterset = filtersets.RackTypeFilterSet
  573. filterset_form = forms.RackTypeFilterForm
  574. table = tables.RackTypeTable
  575. @register_model_view(RackType)
  576. class RackTypeView(GetRelatedModelsMixin, generic.ObjectView):
  577. queryset = RackType.objects.all()
  578. def get_extra_context(self, request, instance):
  579. return {
  580. 'related_models': self.get_related_models(request, instance),
  581. }
  582. @register_model_view(RackType, 'add', detail=False)
  583. @register_model_view(RackType, 'edit')
  584. class RackTypeEditView(generic.ObjectEditView):
  585. queryset = RackType.objects.all()
  586. form = forms.RackTypeForm
  587. @register_model_view(RackType, 'delete')
  588. class RackTypeDeleteView(generic.ObjectDeleteView):
  589. queryset = RackType.objects.all()
  590. @register_model_view(RackType, 'bulk_import', detail=False)
  591. class RackTypeBulkImportView(generic.BulkImportView):
  592. queryset = RackType.objects.all()
  593. model_form = forms.RackTypeImportForm
  594. @register_model_view(RackType, 'bulk_edit', path='edit', detail=False)
  595. class RackTypeBulkEditView(generic.BulkEditView):
  596. queryset = RackType.objects.all()
  597. filterset = filtersets.RackTypeFilterSet
  598. table = tables.RackTypeTable
  599. form = forms.RackTypeBulkEditForm
  600. @register_model_view(RackType, 'bulk_delete', path='delete', detail=False)
  601. class RackTypeBulkDeleteView(generic.BulkDeleteView):
  602. queryset = RackType.objects.all()
  603. filterset = filtersets.RackTypeFilterSet
  604. table = tables.RackTypeTable
  605. #
  606. # Racks
  607. #
  608. @register_model_view(Rack, 'list', path='', detail=False)
  609. class RackListView(generic.ObjectListView):
  610. queryset = Rack.objects.annotate(
  611. device_count=count_related(Device, 'rack')
  612. )
  613. filterset = filtersets.RackFilterSet
  614. filterset_form = forms.RackFilterForm
  615. table = tables.RackTable
  616. template_name = 'dcim/rack_list.html'
  617. class RackElevationListView(generic.ObjectListView):
  618. """
  619. Display a set of rack elevations side-by-side.
  620. """
  621. queryset = Rack.objects.prefetch_related('role')
  622. def get(self, request):
  623. racks = filtersets.RackFilterSet(request.GET, self.queryset).qs
  624. total_count = racks.count()
  625. # Ordering
  626. ORDERING_CHOICES = {
  627. 'name': 'Name (A-Z)',
  628. '-name': 'Name (Z-A)',
  629. 'facility_id': 'Facility ID (A-Z)',
  630. '-facility_id': 'Facility ID (Z-A)',
  631. }
  632. sort = request.GET.get('sort', 'name')
  633. if sort not in ORDERING_CHOICES:
  634. sort = 'name'
  635. racks = racks.order_by(sort)
  636. # Pagination
  637. per_page = get_paginate_count(request)
  638. page_number = request.GET.get('page', 1)
  639. paginator = EnhancedPaginator(racks, per_page)
  640. try:
  641. page = paginator.page(page_number)
  642. except PageNotAnInteger:
  643. page = paginator.page(1)
  644. except EmptyPage:
  645. page = paginator.page(paginator.num_pages)
  646. # Determine rack face
  647. rack_face = request.GET.get('face', DeviceFaceChoices.FACE_FRONT)
  648. if rack_face not in DeviceFaceChoices.values():
  649. rack_face = DeviceFaceChoices.FACE_FRONT
  650. return render(request, 'dcim/rack_elevation_list.html', {
  651. 'paginator': paginator,
  652. 'page': page,
  653. 'total_count': total_count,
  654. 'sort': sort,
  655. 'sort_display_name': ORDERING_CHOICES[sort],
  656. 'sort_choices': ORDERING_CHOICES,
  657. 'rack_face': rack_face,
  658. 'filter_form': forms.RackElevationFilterForm(request.GET),
  659. 'model': self.queryset.model,
  660. })
  661. @register_model_view(Rack)
  662. class RackView(GetRelatedModelsMixin, generic.ObjectView):
  663. queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role')
  664. def get_extra_context(self, request, instance):
  665. peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=instance.site)
  666. if instance.location:
  667. peer_racks = peer_racks.filter(location=instance.location)
  668. else:
  669. peer_racks = peer_racks.filter(location__isnull=True)
  670. next_rack = peer_racks.filter(name__gt=instance.name).first()
  671. prev_rack = peer_racks.filter(name__lt=instance.name).reverse().first()
  672. # Determine any additional parameters to pass when embedding the rack elevations
  673. svg_extra = '&'.join([
  674. f'highlight=id:{pk}' for pk in request.GET.getlist('device')
  675. ])
  676. return {
  677. 'related_models': self.get_related_models(
  678. request,
  679. instance,
  680. omit=(CableTermination,),
  681. extra=(
  682. (
  683. VLANGroup.objects.restrict(request.user, 'view').filter(
  684. scope_type=ContentType.objects.get_for_model(Rack),
  685. scope_id=instance.pk
  686. ), 'rack'),
  687. ),
  688. ),
  689. 'next_rack': next_rack,
  690. 'prev_rack': prev_rack,
  691. 'svg_extra': svg_extra,
  692. 'peer_racks': peer_racks,
  693. }
  694. @register_model_view(Rack, 'reservations')
  695. class RackRackReservationsView(generic.ObjectChildrenView):
  696. queryset = Rack.objects.all()
  697. child_model = RackReservation
  698. table = tables.RackReservationTable
  699. filterset = filtersets.RackReservationFilterSet
  700. filterset_form = forms.RackReservationFilterForm
  701. template_name = 'dcim/rack/reservations.html'
  702. tab = ViewTab(
  703. label=_('Reservations'),
  704. badge=lambda obj: obj.reservations.count(),
  705. permission='dcim.view_rackreservation',
  706. weight=510
  707. )
  708. def get_children(self, request, parent):
  709. return parent.reservations.restrict(request.user, 'view')
  710. @register_model_view(Rack, 'nonracked_devices', 'nonracked-devices')
  711. class RackNonRackedView(generic.ObjectChildrenView):
  712. queryset = Rack.objects.all()
  713. child_model = Device
  714. table = tables.DeviceTable
  715. filterset = filtersets.DeviceFilterSet
  716. filterset_form = forms.DeviceFilterForm
  717. template_name = 'dcim/rack/non_racked_devices.html'
  718. tab = ViewTab(
  719. label=_('Non-Racked Devices'),
  720. badge=lambda obj: obj.devices.filter(rack=obj, position__isnull=True, parent_bay__isnull=True).count(),
  721. weight=500,
  722. permission='dcim.view_device',
  723. )
  724. def get_children(self, request, parent):
  725. return parent.devices.restrict(request.user, 'view').filter(
  726. rack=parent, position__isnull=True, parent_bay__isnull=True
  727. )
  728. @register_model_view(Rack, 'add', detail=False)
  729. @register_model_view(Rack, 'edit')
  730. class RackEditView(generic.ObjectEditView):
  731. queryset = Rack.objects.all()
  732. form = forms.RackForm
  733. @register_model_view(Rack, 'delete')
  734. class RackDeleteView(generic.ObjectDeleteView):
  735. queryset = Rack.objects.all()
  736. @register_model_view(Rack, 'bulk_import', detail=False)
  737. class RackBulkImportView(generic.BulkImportView):
  738. queryset = Rack.objects.all()
  739. model_form = forms.RackImportForm
  740. @register_model_view(Rack, 'bulk_edit', path='edit', detail=False)
  741. class RackBulkEditView(generic.BulkEditView):
  742. queryset = Rack.objects.all()
  743. filterset = filtersets.RackFilterSet
  744. table = tables.RackTable
  745. form = forms.RackBulkEditForm
  746. @register_model_view(Rack, 'bulk_delete', path='delete', detail=False)
  747. class RackBulkDeleteView(generic.BulkDeleteView):
  748. queryset = Rack.objects.all()
  749. filterset = filtersets.RackFilterSet
  750. table = tables.RackTable
  751. #
  752. # Rack reservations
  753. #
  754. @register_model_view(RackReservation, 'list', path='', detail=False)
  755. class RackReservationListView(generic.ObjectListView):
  756. queryset = RackReservation.objects.all()
  757. filterset = filtersets.RackReservationFilterSet
  758. filterset_form = forms.RackReservationFilterForm
  759. table = tables.RackReservationTable
  760. @register_model_view(RackReservation)
  761. class RackReservationView(generic.ObjectView):
  762. queryset = RackReservation.objects.all()
  763. @register_model_view(RackReservation, 'add', detail=False)
  764. @register_model_view(RackReservation, 'edit')
  765. class RackReservationEditView(generic.ObjectEditView):
  766. queryset = RackReservation.objects.all()
  767. form = forms.RackReservationForm
  768. def alter_object(self, obj, request, args, kwargs):
  769. if not obj.pk:
  770. if 'rack' in request.GET:
  771. obj.rack = get_object_or_404(Rack, pk=request.GET.get('rack'))
  772. obj.user = request.user
  773. return obj
  774. @register_model_view(RackReservation, 'delete')
  775. class RackReservationDeleteView(generic.ObjectDeleteView):
  776. queryset = RackReservation.objects.all()
  777. @register_model_view(RackReservation, 'bulk_import', detail=False)
  778. class RackReservationImportView(generic.BulkImportView):
  779. queryset = RackReservation.objects.all()
  780. model_form = forms.RackReservationImportForm
  781. def save_object(self, object_form, request):
  782. """
  783. Assign the currently authenticated user to the RackReservation.
  784. """
  785. instance = object_form.save(commit=False)
  786. instance.user = request.user
  787. instance.save()
  788. return instance
  789. @register_model_view(RackReservation, 'bulk_edit', path='edit', detail=False)
  790. class RackReservationBulkEditView(generic.BulkEditView):
  791. queryset = RackReservation.objects.all()
  792. filterset = filtersets.RackReservationFilterSet
  793. table = tables.RackReservationTable
  794. form = forms.RackReservationBulkEditForm
  795. @register_model_view(RackReservation, 'bulk_delete', path='delete', detail=False)
  796. class RackReservationBulkDeleteView(generic.BulkDeleteView):
  797. queryset = RackReservation.objects.all()
  798. filterset = filtersets.RackReservationFilterSet
  799. table = tables.RackReservationTable
  800. #
  801. # Manufacturers
  802. #
  803. @register_model_view(Manufacturer, 'list', path='', detail=False)
  804. class ManufacturerListView(generic.ObjectListView):
  805. queryset = Manufacturer.objects.annotate(
  806. racktype_count=count_related(RackType, 'manufacturer'),
  807. devicetype_count=count_related(DeviceType, 'manufacturer'),
  808. moduletype_count=count_related(ModuleType, 'manufacturer'),
  809. inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
  810. platform_count=count_related(Platform, 'manufacturer')
  811. )
  812. filterset = filtersets.ManufacturerFilterSet
  813. filterset_form = forms.ManufacturerFilterForm
  814. table = tables.ManufacturerTable
  815. @register_model_view(Manufacturer)
  816. class ManufacturerView(GetRelatedModelsMixin, generic.ObjectView):
  817. queryset = Manufacturer.objects.all()
  818. def get_extra_context(self, request, instance):
  819. return {
  820. 'related_models': self.get_related_models(request, instance, [InventoryItemTemplate]),
  821. }
  822. @register_model_view(Manufacturer, 'add', detail=False)
  823. @register_model_view(Manufacturer, 'edit')
  824. class ManufacturerEditView(generic.ObjectEditView):
  825. queryset = Manufacturer.objects.all()
  826. form = forms.ManufacturerForm
  827. @register_model_view(Manufacturer, 'delete')
  828. class ManufacturerDeleteView(generic.ObjectDeleteView):
  829. queryset = Manufacturer.objects.all()
  830. @register_model_view(Manufacturer, 'bulk_import', detail=False)
  831. class ManufacturerBulkImportView(generic.BulkImportView):
  832. queryset = Manufacturer.objects.all()
  833. model_form = forms.ManufacturerImportForm
  834. @register_model_view(Manufacturer, 'bulk_edit', path='edit', detail=False)
  835. class ManufacturerBulkEditView(generic.BulkEditView):
  836. queryset = Manufacturer.objects.annotate(
  837. devicetype_count=count_related(DeviceType, 'manufacturer'),
  838. moduletype_count=count_related(ModuleType, 'manufacturer'),
  839. inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
  840. platform_count=count_related(Platform, 'manufacturer')
  841. )
  842. filterset = filtersets.ManufacturerFilterSet
  843. table = tables.ManufacturerTable
  844. form = forms.ManufacturerBulkEditForm
  845. @register_model_view(Manufacturer, 'bulk_delete', path='delete', detail=False)
  846. class ManufacturerBulkDeleteView(generic.BulkDeleteView):
  847. queryset = Manufacturer.objects.annotate(
  848. devicetype_count=count_related(DeviceType, 'manufacturer'),
  849. moduletype_count=count_related(ModuleType, 'manufacturer'),
  850. inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
  851. platform_count=count_related(Platform, 'manufacturer')
  852. )
  853. filterset = filtersets.ManufacturerFilterSet
  854. table = tables.ManufacturerTable
  855. #
  856. # Device types
  857. #
  858. @register_model_view(DeviceType, 'list', path='', detail=False)
  859. class DeviceTypeListView(generic.ObjectListView):
  860. queryset = DeviceType.objects.annotate(
  861. instance_count=count_related(Device, 'device_type')
  862. )
  863. filterset = filtersets.DeviceTypeFilterSet
  864. filterset_form = forms.DeviceTypeFilterForm
  865. table = tables.DeviceTypeTable
  866. @register_model_view(DeviceType)
  867. class DeviceTypeView(GetRelatedModelsMixin, generic.ObjectView):
  868. queryset = DeviceType.objects.all()
  869. def get_extra_context(self, request, instance):
  870. return {
  871. 'related_models': self.get_related_models(request, instance, omit=[
  872. ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, FrontPortTemplate,
  873. InventoryItemTemplate, InterfaceTemplate, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate,
  874. RearPortTemplate,
  875. ]),
  876. }
  877. @register_model_view(DeviceType, 'add', detail=False)
  878. @register_model_view(DeviceType, 'edit')
  879. class DeviceTypeEditView(generic.ObjectEditView):
  880. queryset = DeviceType.objects.all()
  881. form = forms.DeviceTypeForm
  882. @register_model_view(DeviceType, 'delete')
  883. class DeviceTypeDeleteView(generic.ObjectDeleteView):
  884. queryset = DeviceType.objects.all()
  885. @register_model_view(DeviceType, 'consoleports', path='console-ports')
  886. class DeviceTypeConsolePortsView(DeviceTypeComponentsView):
  887. child_model = ConsolePortTemplate
  888. table = tables.ConsolePortTemplateTable
  889. filterset = filtersets.ConsolePortTemplateFilterSet
  890. viewname = 'dcim:devicetype_consoleports'
  891. tab = ViewTab(
  892. label=_('Console Ports'),
  893. badge=lambda obj: obj.console_port_template_count,
  894. permission='dcim.view_consoleporttemplate',
  895. weight=550,
  896. hide_if_empty=True
  897. )
  898. @register_model_view(DeviceType, 'consoleserverports', path='console-server-ports')
  899. class DeviceTypeConsoleServerPortsView(DeviceTypeComponentsView):
  900. child_model = ConsoleServerPortTemplate
  901. table = tables.ConsoleServerPortTemplateTable
  902. filterset = filtersets.ConsoleServerPortTemplateFilterSet
  903. viewname = 'dcim:devicetype_consoleserverports'
  904. tab = ViewTab(
  905. label=_('Console Server Ports'),
  906. badge=lambda obj: obj.console_server_port_template_count,
  907. permission='dcim.view_consoleserverporttemplate',
  908. weight=560,
  909. hide_if_empty=True
  910. )
  911. @register_model_view(DeviceType, 'powerports', path='power-ports')
  912. class DeviceTypePowerPortsView(DeviceTypeComponentsView):
  913. child_model = PowerPortTemplate
  914. table = tables.PowerPortTemplateTable
  915. filterset = filtersets.PowerPortTemplateFilterSet
  916. viewname = 'dcim:devicetype_powerports'
  917. tab = ViewTab(
  918. label=_('Power Ports'),
  919. badge=lambda obj: obj.power_port_template_count,
  920. permission='dcim.view_powerporttemplate',
  921. weight=570,
  922. hide_if_empty=True
  923. )
  924. @register_model_view(DeviceType, 'poweroutlets', path='power-outlets')
  925. class DeviceTypePowerOutletsView(DeviceTypeComponentsView):
  926. child_model = PowerOutletTemplate
  927. table = tables.PowerOutletTemplateTable
  928. filterset = filtersets.PowerOutletTemplateFilterSet
  929. viewname = 'dcim:devicetype_poweroutlets'
  930. tab = ViewTab(
  931. label=_('Power Outlets'),
  932. badge=lambda obj: obj.power_outlet_template_count,
  933. permission='dcim.view_poweroutlettemplate',
  934. weight=580,
  935. hide_if_empty=True
  936. )
  937. @register_model_view(DeviceType, 'interfaces')
  938. class DeviceTypeInterfacesView(DeviceTypeComponentsView):
  939. child_model = InterfaceTemplate
  940. table = tables.InterfaceTemplateTable
  941. filterset = filtersets.InterfaceTemplateFilterSet
  942. viewname = 'dcim:devicetype_interfaces'
  943. tab = ViewTab(
  944. label=_('Interfaces'),
  945. badge=lambda obj: obj.interface_template_count,
  946. permission='dcim.view_interfacetemplate',
  947. weight=520,
  948. hide_if_empty=True
  949. )
  950. @register_model_view(DeviceType, 'frontports', path='front-ports')
  951. class DeviceTypeFrontPortsView(DeviceTypeComponentsView):
  952. child_model = FrontPortTemplate
  953. table = tables.FrontPortTemplateTable
  954. filterset = filtersets.FrontPortTemplateFilterSet
  955. viewname = 'dcim:devicetype_frontports'
  956. tab = ViewTab(
  957. label=_('Front Ports'),
  958. badge=lambda obj: obj.front_port_template_count,
  959. permission='dcim.view_frontporttemplate',
  960. weight=530,
  961. hide_if_empty=True
  962. )
  963. @register_model_view(DeviceType, 'rearports', path='rear-ports')
  964. class DeviceTypeRearPortsView(DeviceTypeComponentsView):
  965. child_model = RearPortTemplate
  966. table = tables.RearPortTemplateTable
  967. filterset = filtersets.RearPortTemplateFilterSet
  968. viewname = 'dcim:devicetype_rearports'
  969. tab = ViewTab(
  970. label=_('Rear Ports'),
  971. badge=lambda obj: obj.rear_port_template_count,
  972. permission='dcim.view_rearporttemplate',
  973. weight=540,
  974. hide_if_empty=True
  975. )
  976. @register_model_view(DeviceType, 'modulebays', path='module-bays')
  977. class DeviceTypeModuleBaysView(DeviceTypeComponentsView):
  978. child_model = ModuleBayTemplate
  979. table = tables.ModuleBayTemplateTable
  980. filterset = filtersets.ModuleBayTemplateFilterSet
  981. viewname = 'dcim:devicetype_modulebays'
  982. tab = ViewTab(
  983. label=_('Module Bays'),
  984. badge=lambda obj: obj.module_bay_template_count,
  985. permission='dcim.view_modulebaytemplate',
  986. weight=510,
  987. hide_if_empty=True
  988. )
  989. @register_model_view(DeviceType, 'devicebays', path='device-bays')
  990. class DeviceTypeDeviceBaysView(DeviceTypeComponentsView):
  991. child_model = DeviceBayTemplate
  992. table = tables.DeviceBayTemplateTable
  993. filterset = filtersets.DeviceBayTemplateFilterSet
  994. viewname = 'dcim:devicetype_devicebays'
  995. tab = ViewTab(
  996. label=_('Device Bays'),
  997. badge=lambda obj: obj.device_bay_template_count,
  998. permission='dcim.view_devicebaytemplate',
  999. weight=500,
  1000. hide_if_empty=True
  1001. )
  1002. @register_model_view(DeviceType, 'inventoryitems', path='inventory-items')
  1003. class DeviceTypeInventoryItemsView(DeviceTypeComponentsView):
  1004. child_model = InventoryItemTemplate
  1005. table = tables.InventoryItemTemplateTable
  1006. filterset = filtersets.InventoryItemTemplateFilterSet
  1007. viewname = 'dcim:devicetype_inventoryitems'
  1008. tab = ViewTab(
  1009. label=_('Inventory Items'),
  1010. badge=lambda obj: obj.inventory_item_template_count,
  1011. permission='dcim.view_inventoryitemtemplate',
  1012. weight=590,
  1013. hide_if_empty=True
  1014. )
  1015. @register_model_view(DeviceType, 'bulk_import', detail=False)
  1016. class DeviceTypeImportView(generic.BulkImportView):
  1017. additional_permissions = [
  1018. 'dcim.add_devicetype',
  1019. 'dcim.add_consoleporttemplate',
  1020. 'dcim.add_consoleserverporttemplate',
  1021. 'dcim.add_powerporttemplate',
  1022. 'dcim.add_poweroutlettemplate',
  1023. 'dcim.add_interfacetemplate',
  1024. 'dcim.add_frontporttemplate',
  1025. 'dcim.add_rearporttemplate',
  1026. 'dcim.add_modulebaytemplate',
  1027. 'dcim.add_devicebaytemplate',
  1028. 'dcim.add_inventoryitemtemplate',
  1029. ]
  1030. queryset = DeviceType.objects.all()
  1031. model_form = forms.DeviceTypeImportForm
  1032. related_object_forms = {
  1033. 'console-ports': forms.ConsolePortTemplateImportForm,
  1034. 'console-server-ports': forms.ConsoleServerPortTemplateImportForm,
  1035. 'power-ports': forms.PowerPortTemplateImportForm,
  1036. 'power-outlets': forms.PowerOutletTemplateImportForm,
  1037. 'interfaces': forms.InterfaceTemplateImportForm,
  1038. 'rear-ports': forms.RearPortTemplateImportForm,
  1039. 'front-ports': forms.FrontPortTemplateImportForm,
  1040. 'module-bays': forms.ModuleBayTemplateImportForm,
  1041. 'device-bays': forms.DeviceBayTemplateImportForm,
  1042. 'inventory-items': forms.InventoryItemTemplateImportForm,
  1043. }
  1044. def prep_related_object_data(self, parent, data):
  1045. data.update({'device_type': parent})
  1046. return data
  1047. @register_model_view(DeviceType, 'bulk_edit', path='edit', detail=False)
  1048. class DeviceTypeBulkEditView(generic.BulkEditView):
  1049. queryset = DeviceType.objects.annotate(
  1050. instance_count=count_related(Device, 'device_type')
  1051. )
  1052. filterset = filtersets.DeviceTypeFilterSet
  1053. table = tables.DeviceTypeTable
  1054. form = forms.DeviceTypeBulkEditForm
  1055. @register_model_view(DeviceType, 'bulk_delete', path='delete', detail=False)
  1056. class DeviceTypeBulkDeleteView(generic.BulkDeleteView):
  1057. queryset = DeviceType.objects.annotate(
  1058. instance_count=count_related(Device, 'device_type')
  1059. )
  1060. filterset = filtersets.DeviceTypeFilterSet
  1061. table = tables.DeviceTypeTable
  1062. #
  1063. # Module type profiles
  1064. #
  1065. @register_model_view(ModuleTypeProfile, 'list', path='', detail=False)
  1066. class ModuleTypeProfileListView(generic.ObjectListView):
  1067. queryset = ModuleTypeProfile.objects.annotate(
  1068. instance_count=count_related(ModuleType, 'profile')
  1069. )
  1070. filterset = filtersets.ModuleTypeProfileFilterSet
  1071. filterset_form = forms.ModuleTypeProfileFilterForm
  1072. table = tables.ModuleTypeProfileTable
  1073. @register_model_view(ModuleTypeProfile)
  1074. class ModuleTypeProfileView(GetRelatedModelsMixin, generic.ObjectView):
  1075. queryset = ModuleTypeProfile.objects.all()
  1076. @register_model_view(ModuleTypeProfile, 'add', detail=False)
  1077. @register_model_view(ModuleTypeProfile, 'edit')
  1078. class ModuleTypeProfileEditView(generic.ObjectEditView):
  1079. queryset = ModuleTypeProfile.objects.all()
  1080. form = forms.ModuleTypeProfileForm
  1081. @register_model_view(ModuleTypeProfile, 'delete')
  1082. class ModuleTypeProfileDeleteView(generic.ObjectDeleteView):
  1083. queryset = ModuleTypeProfile.objects.all()
  1084. @register_model_view(ModuleTypeProfile, 'bulk_import', detail=False)
  1085. class ModuleTypeProfileBulkImportView(generic.BulkImportView):
  1086. queryset = ModuleTypeProfile.objects.all()
  1087. model_form = forms.ModuleTypeProfileImportForm
  1088. @register_model_view(ModuleTypeProfile, 'bulk_edit', path='edit', detail=False)
  1089. class ModuleTypeProfileBulkEditView(generic.BulkEditView):
  1090. queryset = ModuleTypeProfile.objects.annotate(
  1091. instance_count=count_related(Module, 'module_type')
  1092. )
  1093. filterset = filtersets.ModuleTypeProfileFilterSet
  1094. table = tables.ModuleTypeProfileTable
  1095. form = forms.ModuleTypeProfileBulkEditForm
  1096. @register_model_view(ModuleTypeProfile, 'bulk_delete', path='delete', detail=False)
  1097. class ModuleTypeProfileBulkDeleteView(generic.BulkDeleteView):
  1098. queryset = ModuleTypeProfile.objects.annotate(
  1099. instance_count=count_related(Module, 'module_type')
  1100. )
  1101. filterset = filtersets.ModuleTypeProfileFilterSet
  1102. table = tables.ModuleTypeProfileTable
  1103. #
  1104. # Module types
  1105. #
  1106. @register_model_view(ModuleType, 'list', path='', detail=False)
  1107. class ModuleTypeListView(generic.ObjectListView):
  1108. queryset = ModuleType.objects.annotate(
  1109. instance_count=count_related(Module, 'module_type')
  1110. )
  1111. filterset = filtersets.ModuleTypeFilterSet
  1112. filterset_form = forms.ModuleTypeFilterForm
  1113. table = tables.ModuleTypeTable
  1114. @register_model_view(ModuleType)
  1115. class ModuleTypeView(GetRelatedModelsMixin, generic.ObjectView):
  1116. queryset = ModuleType.objects.all()
  1117. def get_extra_context(self, request, instance):
  1118. return {
  1119. 'related_models': self.get_related_models(request, instance, omit=[
  1120. ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, FrontPortTemplate,
  1121. InventoryItemTemplate, InterfaceTemplate, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate,
  1122. RearPortTemplate,
  1123. ]),
  1124. }
  1125. @register_model_view(ModuleType, 'add', detail=False)
  1126. @register_model_view(ModuleType, 'edit')
  1127. class ModuleTypeEditView(generic.ObjectEditView):
  1128. queryset = ModuleType.objects.all()
  1129. form = forms.ModuleTypeForm
  1130. @register_model_view(ModuleType, 'delete')
  1131. class ModuleTypeDeleteView(generic.ObjectDeleteView):
  1132. queryset = ModuleType.objects.all()
  1133. @register_model_view(ModuleType, 'consoleports', path='console-ports')
  1134. class ModuleTypeConsolePortsView(ModuleTypeComponentsView):
  1135. child_model = ConsolePortTemplate
  1136. table = tables.ConsolePortTemplateTable
  1137. filterset = filtersets.ConsolePortTemplateFilterSet
  1138. viewname = 'dcim:moduletype_consoleports'
  1139. tab = ViewTab(
  1140. label=_('Console Ports'),
  1141. badge=lambda obj: obj.consoleporttemplates.count(),
  1142. permission='dcim.view_consoleporttemplate',
  1143. weight=530,
  1144. hide_if_empty=True
  1145. )
  1146. @register_model_view(ModuleType, 'consoleserverports', path='console-server-ports')
  1147. class ModuleTypeConsoleServerPortsView(ModuleTypeComponentsView):
  1148. child_model = ConsoleServerPortTemplate
  1149. table = tables.ConsoleServerPortTemplateTable
  1150. filterset = filtersets.ConsoleServerPortTemplateFilterSet
  1151. viewname = 'dcim:moduletype_consoleserverports'
  1152. tab = ViewTab(
  1153. label=_('Console Server Ports'),
  1154. badge=lambda obj: obj.consoleserverporttemplates.count(),
  1155. permission='dcim.view_consoleserverporttemplate',
  1156. weight=540,
  1157. hide_if_empty=True
  1158. )
  1159. @register_model_view(ModuleType, 'powerports', path='power-ports')
  1160. class ModuleTypePowerPortsView(ModuleTypeComponentsView):
  1161. child_model = PowerPortTemplate
  1162. table = tables.PowerPortTemplateTable
  1163. filterset = filtersets.PowerPortTemplateFilterSet
  1164. viewname = 'dcim:moduletype_powerports'
  1165. tab = ViewTab(
  1166. label=_('Power Ports'),
  1167. badge=lambda obj: obj.powerporttemplates.count(),
  1168. permission='dcim.view_powerporttemplate',
  1169. weight=550,
  1170. hide_if_empty=True
  1171. )
  1172. @register_model_view(ModuleType, 'poweroutlets', path='power-outlets')
  1173. class ModuleTypePowerOutletsView(ModuleTypeComponentsView):
  1174. child_model = PowerOutletTemplate
  1175. table = tables.PowerOutletTemplateTable
  1176. filterset = filtersets.PowerOutletTemplateFilterSet
  1177. viewname = 'dcim:moduletype_poweroutlets'
  1178. tab = ViewTab(
  1179. label=_('Power Outlets'),
  1180. badge=lambda obj: obj.poweroutlettemplates.count(),
  1181. permission='dcim.view_poweroutlettemplate',
  1182. weight=560,
  1183. hide_if_empty=True
  1184. )
  1185. @register_model_view(ModuleType, 'interfaces')
  1186. class ModuleTypeInterfacesView(ModuleTypeComponentsView):
  1187. child_model = InterfaceTemplate
  1188. table = tables.InterfaceTemplateTable
  1189. filterset = filtersets.InterfaceTemplateFilterSet
  1190. viewname = 'dcim:moduletype_interfaces'
  1191. tab = ViewTab(
  1192. label=_('Interfaces'),
  1193. badge=lambda obj: obj.interfacetemplates.count(),
  1194. permission='dcim.view_interfacetemplate',
  1195. weight=500,
  1196. hide_if_empty=True
  1197. )
  1198. @register_model_view(ModuleType, 'frontports', path='front-ports')
  1199. class ModuleTypeFrontPortsView(ModuleTypeComponentsView):
  1200. child_model = FrontPortTemplate
  1201. table = tables.FrontPortTemplateTable
  1202. filterset = filtersets.FrontPortTemplateFilterSet
  1203. viewname = 'dcim:moduletype_frontports'
  1204. tab = ViewTab(
  1205. label=_('Front Ports'),
  1206. badge=lambda obj: obj.frontporttemplates.count(),
  1207. permission='dcim.view_frontporttemplate',
  1208. weight=510,
  1209. hide_if_empty=True
  1210. )
  1211. @register_model_view(ModuleType, 'rearports', path='rear-ports')
  1212. class ModuleTypeRearPortsView(ModuleTypeComponentsView):
  1213. child_model = RearPortTemplate
  1214. table = tables.RearPortTemplateTable
  1215. filterset = filtersets.RearPortTemplateFilterSet
  1216. viewname = 'dcim:moduletype_rearports'
  1217. tab = ViewTab(
  1218. label=_('Rear Ports'),
  1219. badge=lambda obj: obj.rearporttemplates.count(),
  1220. permission='dcim.view_rearporttemplate',
  1221. weight=520,
  1222. hide_if_empty=True
  1223. )
  1224. @register_model_view(ModuleType, 'modulebays', path='module-bays')
  1225. class ModuleTypeModuleBaysView(ModuleTypeComponentsView):
  1226. child_model = ModuleBayTemplate
  1227. table = tables.ModuleBayTemplateTable
  1228. filterset = filtersets.ModuleBayTemplateFilterSet
  1229. viewname = 'dcim:moduletype_modulebays'
  1230. tab = ViewTab(
  1231. label=_('Module Bays'),
  1232. badge=lambda obj: obj.modulebaytemplates.count(),
  1233. permission='dcim.view_modulebaytemplate',
  1234. weight=570,
  1235. hide_if_empty=True
  1236. )
  1237. @register_model_view(ModuleType, 'bulk_import', detail=False)
  1238. class ModuleTypeImportView(generic.BulkImportView):
  1239. additional_permissions = [
  1240. 'dcim.add_moduletype',
  1241. 'dcim.add_consoleporttemplate',
  1242. 'dcim.add_consoleserverporttemplate',
  1243. 'dcim.add_powerporttemplate',
  1244. 'dcim.add_poweroutlettemplate',
  1245. 'dcim.add_interfacetemplate',
  1246. 'dcim.add_frontporttemplate',
  1247. 'dcim.add_rearporttemplate',
  1248. ]
  1249. queryset = ModuleType.objects.all()
  1250. model_form = forms.ModuleTypeImportForm
  1251. related_object_forms = {
  1252. 'console-ports': forms.ConsolePortTemplateImportForm,
  1253. 'console-server-ports': forms.ConsoleServerPortTemplateImportForm,
  1254. 'power-ports': forms.PowerPortTemplateImportForm,
  1255. 'power-outlets': forms.PowerOutletTemplateImportForm,
  1256. 'interfaces': forms.InterfaceTemplateImportForm,
  1257. 'rear-ports': forms.RearPortTemplateImportForm,
  1258. 'front-ports': forms.FrontPortTemplateImportForm,
  1259. }
  1260. def prep_related_object_data(self, parent, data):
  1261. data.update({'module_type': parent})
  1262. return data
  1263. @register_model_view(ModuleType, 'bulk_edit', path='edit', detail=False)
  1264. class ModuleTypeBulkEditView(generic.BulkEditView):
  1265. queryset = ModuleType.objects.annotate(
  1266. instance_count=count_related(Module, 'module_type')
  1267. )
  1268. filterset = filtersets.ModuleTypeFilterSet
  1269. table = tables.ModuleTypeTable
  1270. form = forms.ModuleTypeBulkEditForm
  1271. @register_model_view(ModuleType, 'bulk_delete', path='delete', detail=False)
  1272. class ModuleTypeBulkDeleteView(generic.BulkDeleteView):
  1273. queryset = ModuleType.objects.annotate(
  1274. instance_count=count_related(Module, 'module_type')
  1275. )
  1276. filterset = filtersets.ModuleTypeFilterSet
  1277. table = tables.ModuleTypeTable
  1278. #
  1279. # Console port templates
  1280. #
  1281. @register_model_view(ConsolePortTemplate, 'add', detail=False)
  1282. class ConsolePortTemplateCreateView(generic.ComponentCreateView):
  1283. queryset = ConsolePortTemplate.objects.all()
  1284. form = forms.ConsolePortTemplateCreateForm
  1285. model_form = forms.ConsolePortTemplateForm
  1286. @register_model_view(ConsolePortTemplate, 'edit')
  1287. class ConsolePortTemplateEditView(generic.ObjectEditView):
  1288. queryset = ConsolePortTemplate.objects.all()
  1289. form = forms.ConsolePortTemplateForm
  1290. @register_model_view(ConsolePortTemplate, 'delete')
  1291. class ConsolePortTemplateDeleteView(generic.ObjectDeleteView):
  1292. queryset = ConsolePortTemplate.objects.all()
  1293. @register_model_view(ConsolePortTemplate, 'bulk_edit', path='edit', detail=False)
  1294. class ConsolePortTemplateBulkEditView(generic.BulkEditView):
  1295. queryset = ConsolePortTemplate.objects.all()
  1296. table = tables.ConsolePortTemplateTable
  1297. form = forms.ConsolePortTemplateBulkEditForm
  1298. @register_model_view(ConsolePortTemplate, 'bulk_rename', path='rename', detail=False)
  1299. class ConsolePortTemplateBulkRenameView(generic.BulkRenameView):
  1300. queryset = ConsolePortTemplate.objects.all()
  1301. @register_model_view(ConsolePortTemplate, 'bulk_delete', path='delete', detail=False)
  1302. class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView):
  1303. queryset = ConsolePortTemplate.objects.all()
  1304. table = tables.ConsolePortTemplateTable
  1305. #
  1306. # Console server port templates
  1307. #
  1308. @register_model_view(ConsoleServerPortTemplate, 'add', detail=False)
  1309. class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView):
  1310. queryset = ConsoleServerPortTemplate.objects.all()
  1311. form = forms.ConsoleServerPortTemplateCreateForm
  1312. model_form = forms.ConsoleServerPortTemplateForm
  1313. @register_model_view(ConsoleServerPortTemplate, 'edit')
  1314. class ConsoleServerPortTemplateEditView(generic.ObjectEditView):
  1315. queryset = ConsoleServerPortTemplate.objects.all()
  1316. form = forms.ConsoleServerPortTemplateForm
  1317. @register_model_view(ConsoleServerPortTemplate, 'delete')
  1318. class ConsoleServerPortTemplateDeleteView(generic.ObjectDeleteView):
  1319. queryset = ConsoleServerPortTemplate.objects.all()
  1320. @register_model_view(ConsoleServerPortTemplate, 'bulk_edit', path='edit', detail=False)
  1321. class ConsoleServerPortTemplateBulkEditView(generic.BulkEditView):
  1322. queryset = ConsoleServerPortTemplate.objects.all()
  1323. table = tables.ConsoleServerPortTemplateTable
  1324. form = forms.ConsoleServerPortTemplateBulkEditForm
  1325. @register_model_view(ConsoleServerPortTemplate, 'bulk_rename', detail=False)
  1326. class ConsoleServerPortTemplateBulkRenameView(generic.BulkRenameView):
  1327. queryset = ConsoleServerPortTemplate.objects.all()
  1328. @register_model_view(ConsoleServerPortTemplate, 'bulk_delete', path='delete', detail=False)
  1329. class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView):
  1330. queryset = ConsoleServerPortTemplate.objects.all()
  1331. table = tables.ConsoleServerPortTemplateTable
  1332. #
  1333. # Power port templates
  1334. #
  1335. @register_model_view(PowerPortTemplate, 'add', detail=False)
  1336. class PowerPortTemplateCreateView(generic.ComponentCreateView):
  1337. queryset = PowerPortTemplate.objects.all()
  1338. form = forms.PowerPortTemplateCreateForm
  1339. model_form = forms.PowerPortTemplateForm
  1340. @register_model_view(PowerPortTemplate, 'edit')
  1341. class PowerPortTemplateEditView(generic.ObjectEditView):
  1342. queryset = PowerPortTemplate.objects.all()
  1343. form = forms.PowerPortTemplateForm
  1344. @register_model_view(PowerPortTemplate, 'delete')
  1345. class PowerPortTemplateDeleteView(generic.ObjectDeleteView):
  1346. queryset = PowerPortTemplate.objects.all()
  1347. @register_model_view(PowerPortTemplate, 'bulk_edit', path='edit', detail=False)
  1348. class PowerPortTemplateBulkEditView(generic.BulkEditView):
  1349. queryset = PowerPortTemplate.objects.all()
  1350. table = tables.PowerPortTemplateTable
  1351. form = forms.PowerPortTemplateBulkEditForm
  1352. @register_model_view(PowerPortTemplate, 'bulk_rename', path='rename', detail=False)
  1353. class PowerPortTemplateBulkRenameView(generic.BulkRenameView):
  1354. queryset = PowerPortTemplate.objects.all()
  1355. @register_model_view(PowerPortTemplate, 'bulk_delete', path='delete', detail=False)
  1356. class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView):
  1357. queryset = PowerPortTemplate.objects.all()
  1358. table = tables.PowerPortTemplateTable
  1359. #
  1360. # Power outlet templates
  1361. #
  1362. @register_model_view(PowerOutletTemplate, 'add', detail=False)
  1363. class PowerOutletTemplateCreateView(generic.ComponentCreateView):
  1364. queryset = PowerOutletTemplate.objects.all()
  1365. form = forms.PowerOutletTemplateCreateForm
  1366. model_form = forms.PowerOutletTemplateForm
  1367. @register_model_view(PowerOutletTemplate, 'edit')
  1368. class PowerOutletTemplateEditView(generic.ObjectEditView):
  1369. queryset = PowerOutletTemplate.objects.all()
  1370. form = forms.PowerOutletTemplateForm
  1371. @register_model_view(PowerOutletTemplate, 'delete')
  1372. class PowerOutletTemplateDeleteView(generic.ObjectDeleteView):
  1373. queryset = PowerOutletTemplate.objects.all()
  1374. @register_model_view(PowerOutletTemplate, 'bulk_edit', path='edit', detail=False)
  1375. class PowerOutletTemplateBulkEditView(generic.BulkEditView):
  1376. queryset = PowerOutletTemplate.objects.all()
  1377. table = tables.PowerOutletTemplateTable
  1378. form = forms.PowerOutletTemplateBulkEditForm
  1379. @register_model_view(PowerOutletTemplate, 'bulk_rename', path='rename', detail=False)
  1380. class PowerOutletTemplateBulkRenameView(generic.BulkRenameView):
  1381. queryset = PowerOutletTemplate.objects.all()
  1382. @register_model_view(PowerOutletTemplate, 'bulk_delete', path='delete', detail=False)
  1383. class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView):
  1384. queryset = PowerOutletTemplate.objects.all()
  1385. table = tables.PowerOutletTemplateTable
  1386. #
  1387. # Interface templates
  1388. #
  1389. @register_model_view(InterfaceTemplate, 'add', detail=False)
  1390. class InterfaceTemplateCreateView(generic.ComponentCreateView):
  1391. queryset = InterfaceTemplate.objects.all()
  1392. form = forms.InterfaceTemplateCreateForm
  1393. model_form = forms.InterfaceTemplateForm
  1394. @register_model_view(InterfaceTemplate, 'edit')
  1395. class InterfaceTemplateEditView(generic.ObjectEditView):
  1396. queryset = InterfaceTemplate.objects.all()
  1397. form = forms.InterfaceTemplateForm
  1398. @register_model_view(InterfaceTemplate, 'delete')
  1399. class InterfaceTemplateDeleteView(generic.ObjectDeleteView):
  1400. queryset = InterfaceTemplate.objects.all()
  1401. @register_model_view(InterfaceTemplate, 'bulk_edit', path='edit', detail=False)
  1402. class InterfaceTemplateBulkEditView(generic.BulkEditView):
  1403. queryset = InterfaceTemplate.objects.all()
  1404. table = tables.InterfaceTemplateTable
  1405. form = forms.InterfaceTemplateBulkEditForm
  1406. @register_model_view(InterfaceTemplate, 'bulk_rename', path='rename', detail=False)
  1407. class InterfaceTemplateBulkRenameView(generic.BulkRenameView):
  1408. queryset = InterfaceTemplate.objects.all()
  1409. @register_model_view(InterfaceTemplate, 'bulk_delete', path='delete', detail=False)
  1410. class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView):
  1411. queryset = InterfaceTemplate.objects.all()
  1412. table = tables.InterfaceTemplateTable
  1413. #
  1414. # Front port templates
  1415. #
  1416. @register_model_view(FrontPortTemplate, 'add', detail=False)
  1417. class FrontPortTemplateCreateView(generic.ComponentCreateView):
  1418. queryset = FrontPortTemplate.objects.all()
  1419. form = forms.FrontPortTemplateCreateForm
  1420. model_form = forms.FrontPortTemplateForm
  1421. @register_model_view(FrontPortTemplate, 'edit')
  1422. class FrontPortTemplateEditView(generic.ObjectEditView):
  1423. queryset = FrontPortTemplate.objects.all()
  1424. form = forms.FrontPortTemplateForm
  1425. @register_model_view(FrontPortTemplate, 'delete')
  1426. class FrontPortTemplateDeleteView(generic.ObjectDeleteView):
  1427. queryset = FrontPortTemplate.objects.all()
  1428. @register_model_view(FrontPortTemplate, 'bulk_edit', path='edit', detail=False)
  1429. class FrontPortTemplateBulkEditView(generic.BulkEditView):
  1430. queryset = FrontPortTemplate.objects.all()
  1431. table = tables.FrontPortTemplateTable
  1432. form = forms.FrontPortTemplateBulkEditForm
  1433. @register_model_view(FrontPortTemplate, 'bulk_rename', path='rename', detail=False)
  1434. class FrontPortTemplateBulkRenameView(generic.BulkRenameView):
  1435. queryset = FrontPortTemplate.objects.all()
  1436. @register_model_view(FrontPortTemplate, 'bulk_delete', path='delete', detail=False)
  1437. class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView):
  1438. queryset = FrontPortTemplate.objects.all()
  1439. table = tables.FrontPortTemplateTable
  1440. #
  1441. # Rear port templates
  1442. #
  1443. @register_model_view(RearPortTemplate, 'add', detail=False)
  1444. class RearPortTemplateCreateView(generic.ComponentCreateView):
  1445. queryset = RearPortTemplate.objects.all()
  1446. form = forms.RearPortTemplateCreateForm
  1447. model_form = forms.RearPortTemplateForm
  1448. @register_model_view(RearPortTemplate, 'edit')
  1449. class RearPortTemplateEditView(generic.ObjectEditView):
  1450. queryset = RearPortTemplate.objects.all()
  1451. form = forms.RearPortTemplateForm
  1452. @register_model_view(RearPortTemplate, 'delete')
  1453. class RearPortTemplateDeleteView(generic.ObjectDeleteView):
  1454. queryset = RearPortTemplate.objects.all()
  1455. @register_model_view(RearPortTemplate, 'bulk_edit', path='edit', detail=False)
  1456. class RearPortTemplateBulkEditView(generic.BulkEditView):
  1457. queryset = RearPortTemplate.objects.all()
  1458. table = tables.RearPortTemplateTable
  1459. form = forms.RearPortTemplateBulkEditForm
  1460. @register_model_view(RearPortTemplate, 'bulk_rename', path='rename', detail=False)
  1461. class RearPortTemplateBulkRenameView(generic.BulkRenameView):
  1462. queryset = RearPortTemplate.objects.all()
  1463. @register_model_view(RearPortTemplate, 'bulk_delete', path='delete', detail=False)
  1464. class RearPortTemplateBulkDeleteView(generic.BulkDeleteView):
  1465. queryset = RearPortTemplate.objects.all()
  1466. table = tables.RearPortTemplateTable
  1467. #
  1468. # Module bay templates
  1469. #
  1470. @register_model_view(ModuleBayTemplate, 'add', detail=False)
  1471. class ModuleBayTemplateCreateView(generic.ComponentCreateView):
  1472. queryset = ModuleBayTemplate.objects.all()
  1473. form = forms.ModuleBayTemplateCreateForm
  1474. model_form = forms.ModuleBayTemplateForm
  1475. @register_model_view(ModuleBayTemplate, 'edit')
  1476. class ModuleBayTemplateEditView(generic.ObjectEditView):
  1477. queryset = ModuleBayTemplate.objects.all()
  1478. form = forms.ModuleBayTemplateForm
  1479. @register_model_view(ModuleBayTemplate, 'delete')
  1480. class ModuleBayTemplateDeleteView(generic.ObjectDeleteView):
  1481. queryset = ModuleBayTemplate.objects.all()
  1482. @register_model_view(ModuleBayTemplate, 'bulk_edit', path='edit', detail=False)
  1483. class ModuleBayTemplateBulkEditView(generic.BulkEditView):
  1484. queryset = ModuleBayTemplate.objects.all()
  1485. table = tables.ModuleBayTemplateTable
  1486. form = forms.ModuleBayTemplateBulkEditForm
  1487. @register_model_view(ModuleBayTemplate, 'bulk_rename', path='rename', detail=False)
  1488. class ModuleBayTemplateBulkRenameView(generic.BulkRenameView):
  1489. queryset = ModuleBayTemplate.objects.all()
  1490. @register_model_view(ModuleBayTemplate, 'bulk_delete', path='delete', detail=False)
  1491. class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView):
  1492. queryset = ModuleBayTemplate.objects.all()
  1493. table = tables.ModuleBayTemplateTable
  1494. #
  1495. # Device bay templates
  1496. #
  1497. @register_model_view(DeviceBayTemplate, 'add', detail=False)
  1498. class DeviceBayTemplateCreateView(generic.ComponentCreateView):
  1499. queryset = DeviceBayTemplate.objects.all()
  1500. form = forms.DeviceBayTemplateCreateForm
  1501. model_form = forms.DeviceBayTemplateForm
  1502. @register_model_view(DeviceBayTemplate, 'edit')
  1503. class DeviceBayTemplateEditView(generic.ObjectEditView):
  1504. queryset = DeviceBayTemplate.objects.all()
  1505. form = forms.DeviceBayTemplateForm
  1506. @register_model_view(DeviceBayTemplate, 'delete')
  1507. class DeviceBayTemplateDeleteView(generic.ObjectDeleteView):
  1508. queryset = DeviceBayTemplate.objects.all()
  1509. @register_model_view(DeviceBayTemplate, 'bulk_edit', path='edit', detail=False)
  1510. class DeviceBayTemplateBulkEditView(generic.BulkEditView):
  1511. queryset = DeviceBayTemplate.objects.all()
  1512. table = tables.DeviceBayTemplateTable
  1513. form = forms.DeviceBayTemplateBulkEditForm
  1514. @register_model_view(DeviceBayTemplate, 'bulk_rename', path='rename', detail=False)
  1515. class DeviceBayTemplateBulkRenameView(generic.BulkRenameView):
  1516. queryset = DeviceBayTemplate.objects.all()
  1517. @register_model_view(DeviceBayTemplate, 'bulk_delete', path='delete', detail=False)
  1518. class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView):
  1519. queryset = DeviceBayTemplate.objects.all()
  1520. table = tables.DeviceBayTemplateTable
  1521. #
  1522. # Inventory item templates
  1523. #
  1524. @register_model_view(InventoryItemTemplate, 'add', detail=False)
  1525. class InventoryItemTemplateCreateView(generic.ComponentCreateView):
  1526. queryset = InventoryItemTemplate.objects.all()
  1527. form = forms.InventoryItemTemplateCreateForm
  1528. model_form = forms.InventoryItemTemplateForm
  1529. def alter_object(self, instance, request):
  1530. # Set component (if any)
  1531. component_type = request.GET.get('component_type')
  1532. component_id = request.GET.get('component_id')
  1533. if component_type and component_id:
  1534. content_type = get_object_or_404(ContentType, pk=component_type)
  1535. instance.component = get_object_or_404(content_type.model_class(), pk=component_id)
  1536. return instance
  1537. @register_model_view(InventoryItemTemplate, 'edit')
  1538. class InventoryItemTemplateEditView(generic.ObjectEditView):
  1539. queryset = InventoryItemTemplate.objects.all()
  1540. form = forms.InventoryItemTemplateForm
  1541. @register_model_view(InventoryItemTemplate, 'delete')
  1542. class InventoryItemTemplateDeleteView(generic.ObjectDeleteView):
  1543. queryset = InventoryItemTemplate.objects.all()
  1544. @register_model_view(InventoryItemTemplate, 'bulk_edit', path='edit', detail=False)
  1545. class InventoryItemTemplateBulkEditView(generic.BulkEditView):
  1546. queryset = InventoryItemTemplate.objects.all()
  1547. table = tables.InventoryItemTemplateTable
  1548. form = forms.InventoryItemTemplateBulkEditForm
  1549. @register_model_view(InventoryItemTemplate, 'bulk_rename', path='rename', detail=False)
  1550. class InventoryItemTemplateBulkRenameView(generic.BulkRenameView):
  1551. queryset = InventoryItemTemplate.objects.all()
  1552. @register_model_view(InventoryItemTemplate, 'bulk_delete', path='delete', detail=False)
  1553. class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView):
  1554. queryset = InventoryItemTemplate.objects.all()
  1555. table = tables.InventoryItemTemplateTable
  1556. #
  1557. # Device roles
  1558. #
  1559. @register_model_view(DeviceRole, 'list', path='', detail=False)
  1560. class DeviceRoleListView(generic.ObjectListView):
  1561. queryset = DeviceRole.objects.annotate(
  1562. device_count=count_related(Device, 'role'),
  1563. vm_count=count_related(VirtualMachine, 'role')
  1564. )
  1565. filterset = filtersets.DeviceRoleFilterSet
  1566. filterset_form = forms.DeviceRoleFilterForm
  1567. table = tables.DeviceRoleTable
  1568. @register_model_view(DeviceRole)
  1569. class DeviceRoleView(GetRelatedModelsMixin, generic.ObjectView):
  1570. queryset = DeviceRole.objects.all()
  1571. def get_extra_context(self, request, instance):
  1572. return {
  1573. 'related_models': self.get_related_models(request, instance),
  1574. }
  1575. @register_model_view(DeviceRole, 'add', detail=False)
  1576. @register_model_view(DeviceRole, 'edit')
  1577. class DeviceRoleEditView(generic.ObjectEditView):
  1578. queryset = DeviceRole.objects.all()
  1579. form = forms.DeviceRoleForm
  1580. @register_model_view(DeviceRole, 'delete')
  1581. class DeviceRoleDeleteView(generic.ObjectDeleteView):
  1582. queryset = DeviceRole.objects.all()
  1583. @register_model_view(DeviceRole, 'bulk_import', detail=False)
  1584. class DeviceRoleBulkImportView(generic.BulkImportView):
  1585. queryset = DeviceRole.objects.all()
  1586. model_form = forms.DeviceRoleImportForm
  1587. @register_model_view(DeviceRole, 'bulk_edit', path='edit', detail=False)
  1588. class DeviceRoleBulkEditView(generic.BulkEditView):
  1589. queryset = DeviceRole.objects.annotate(
  1590. device_count=count_related(Device, 'role'),
  1591. vm_count=count_related(VirtualMachine, 'role')
  1592. )
  1593. filterset = filtersets.DeviceRoleFilterSet
  1594. table = tables.DeviceRoleTable
  1595. form = forms.DeviceRoleBulkEditForm
  1596. @register_model_view(DeviceRole, 'bulk_delete', path='delete', detail=False)
  1597. class DeviceRoleBulkDeleteView(generic.BulkDeleteView):
  1598. queryset = DeviceRole.objects.annotate(
  1599. device_count=count_related(Device, 'role'),
  1600. vm_count=count_related(VirtualMachine, 'role')
  1601. )
  1602. filterset = filtersets.DeviceRoleFilterSet
  1603. table = tables.DeviceRoleTable
  1604. #
  1605. # Platforms
  1606. #
  1607. @register_model_view(Platform, 'list', path='', detail=False)
  1608. class PlatformListView(generic.ObjectListView):
  1609. queryset = Platform.objects.annotate(
  1610. device_count=count_related(Device, 'platform'),
  1611. vm_count=count_related(VirtualMachine, 'platform')
  1612. )
  1613. table = tables.PlatformTable
  1614. filterset = filtersets.PlatformFilterSet
  1615. filterset_form = forms.PlatformFilterForm
  1616. @register_model_view(Platform)
  1617. class PlatformView(GetRelatedModelsMixin, generic.ObjectView):
  1618. queryset = Platform.objects.all()
  1619. def get_extra_context(self, request, instance):
  1620. return {
  1621. 'related_models': self.get_related_models(request, instance),
  1622. }
  1623. @register_model_view(Platform, 'add', detail=False)
  1624. @register_model_view(Platform, 'edit')
  1625. class PlatformEditView(generic.ObjectEditView):
  1626. queryset = Platform.objects.all()
  1627. form = forms.PlatformForm
  1628. @register_model_view(Platform, 'delete')
  1629. class PlatformDeleteView(generic.ObjectDeleteView):
  1630. queryset = Platform.objects.all()
  1631. @register_model_view(Platform, 'bulk_import', detail=False)
  1632. class PlatformBulkImportView(generic.BulkImportView):
  1633. queryset = Platform.objects.all()
  1634. model_form = forms.PlatformImportForm
  1635. @register_model_view(Platform, 'bulk_edit', path='edit', detail=False)
  1636. class PlatformBulkEditView(generic.BulkEditView):
  1637. queryset = Platform.objects.all()
  1638. filterset = filtersets.PlatformFilterSet
  1639. table = tables.PlatformTable
  1640. form = forms.PlatformBulkEditForm
  1641. @register_model_view(Platform, 'bulk_delete', path='delete', detail=False)
  1642. class PlatformBulkDeleteView(generic.BulkDeleteView):
  1643. queryset = Platform.objects.all()
  1644. filterset = filtersets.PlatformFilterSet
  1645. table = tables.PlatformTable
  1646. #
  1647. # Devices
  1648. #
  1649. @register_model_view(Device, 'list', path='', detail=False)
  1650. class DeviceListView(generic.ObjectListView):
  1651. queryset = Device.objects.select_related('virtual_chassis')
  1652. filterset = filtersets.DeviceFilterSet
  1653. filterset_form = forms.DeviceFilterForm
  1654. table = tables.DeviceTable
  1655. template_name = 'dcim/device_list.html'
  1656. @register_model_view(Device)
  1657. class DeviceView(generic.ObjectView):
  1658. queryset = Device.objects.all()
  1659. def get_extra_context(self, request, instance):
  1660. # VirtualChassis members
  1661. if instance.virtual_chassis is not None:
  1662. vc_members = Device.objects.restrict(request.user, 'view').filter(
  1663. virtual_chassis=instance.virtual_chassis
  1664. ).order_by('vc_position')
  1665. else:
  1666. vc_members = []
  1667. return {
  1668. 'vc_members': vc_members,
  1669. 'svg_extra': f'highlight=id:{instance.pk}'
  1670. }
  1671. @register_model_view(Device, 'add', detail=False)
  1672. @register_model_view(Device, 'edit')
  1673. class DeviceEditView(generic.ObjectEditView):
  1674. queryset = Device.objects.all()
  1675. form = forms.DeviceForm
  1676. template_name = 'dcim/device_edit.html'
  1677. @register_model_view(Device, 'delete')
  1678. class DeviceDeleteView(generic.ObjectDeleteView):
  1679. queryset = Device.objects.all()
  1680. @register_model_view(Device, 'consoleports', path='console-ports')
  1681. class DeviceConsolePortsView(DeviceComponentsView):
  1682. child_model = ConsolePort
  1683. table = tables.DeviceConsolePortTable
  1684. filterset = filtersets.ConsolePortFilterSet
  1685. filterset_form = forms.ConsolePortFilterForm
  1686. template_name = 'dcim/device/consoleports.html',
  1687. tab = ViewTab(
  1688. label=_('Console Ports'),
  1689. badge=lambda obj: obj.console_port_count,
  1690. permission='dcim.view_consoleport',
  1691. weight=550,
  1692. hide_if_empty=True
  1693. )
  1694. @register_model_view(Device, 'consoleserverports', path='console-server-ports')
  1695. class DeviceConsoleServerPortsView(DeviceComponentsView):
  1696. child_model = ConsoleServerPort
  1697. table = tables.DeviceConsoleServerPortTable
  1698. filterset = filtersets.ConsoleServerPortFilterSet
  1699. filterset_form = forms.ConsoleServerPortFilterForm
  1700. template_name = 'dcim/device/consoleserverports.html'
  1701. tab = ViewTab(
  1702. label=_('Console Server Ports'),
  1703. badge=lambda obj: obj.console_server_port_count,
  1704. permission='dcim.view_consoleserverport',
  1705. weight=560,
  1706. hide_if_empty=True
  1707. )
  1708. @register_model_view(Device, 'powerports', path='power-ports')
  1709. class DevicePowerPortsView(DeviceComponentsView):
  1710. child_model = PowerPort
  1711. table = tables.DevicePowerPortTable
  1712. filterset = filtersets.PowerPortFilterSet
  1713. filterset_form = forms.PowerPortFilterForm
  1714. template_name = 'dcim/device/powerports.html'
  1715. tab = ViewTab(
  1716. label=_('Power Ports'),
  1717. badge=lambda obj: obj.power_port_count,
  1718. permission='dcim.view_powerport',
  1719. weight=570,
  1720. hide_if_empty=True
  1721. )
  1722. @register_model_view(Device, 'poweroutlets', path='power-outlets')
  1723. class DevicePowerOutletsView(DeviceComponentsView):
  1724. child_model = PowerOutlet
  1725. table = tables.DevicePowerOutletTable
  1726. filterset = filtersets.PowerOutletFilterSet
  1727. filterset_form = forms.PowerOutletFilterForm
  1728. template_name = 'dcim/device/poweroutlets.html'
  1729. tab = ViewTab(
  1730. label=_('Power Outlets'),
  1731. badge=lambda obj: obj.power_outlet_count,
  1732. permission='dcim.view_poweroutlet',
  1733. weight=580,
  1734. hide_if_empty=True
  1735. )
  1736. @register_model_view(Device, 'interfaces')
  1737. class DeviceInterfacesView(DeviceComponentsView):
  1738. child_model = Interface
  1739. table = tables.DeviceInterfaceTable
  1740. filterset = filtersets.InterfaceFilterSet
  1741. filterset_form = forms.InterfaceFilterForm
  1742. template_name = 'dcim/device/interfaces.html'
  1743. tab = ViewTab(
  1744. label=_('Interfaces'),
  1745. badge=lambda obj: obj.vc_interfaces().count(),
  1746. permission='dcim.view_interface',
  1747. weight=520,
  1748. hide_if_empty=True
  1749. )
  1750. def get_children(self, request, parent):
  1751. return parent.vc_interfaces().restrict(request.user, 'view').prefetch_related(
  1752. Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
  1753. Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user))
  1754. )
  1755. @register_model_view(Device, 'frontports', path='front-ports')
  1756. class DeviceFrontPortsView(DeviceComponentsView):
  1757. child_model = FrontPort
  1758. table = tables.DeviceFrontPortTable
  1759. filterset = filtersets.FrontPortFilterSet
  1760. filterset_form = forms.FrontPortFilterForm
  1761. template_name = 'dcim/device/frontports.html'
  1762. tab = ViewTab(
  1763. label=_('Front Ports'),
  1764. badge=lambda obj: obj.front_port_count,
  1765. permission='dcim.view_frontport',
  1766. weight=530,
  1767. hide_if_empty=True
  1768. )
  1769. @register_model_view(Device, 'rearports', path='rear-ports')
  1770. class DeviceRearPortsView(DeviceComponentsView):
  1771. child_model = RearPort
  1772. table = tables.DeviceRearPortTable
  1773. filterset = filtersets.RearPortFilterSet
  1774. filterset_form = forms.RearPortFilterForm
  1775. template_name = 'dcim/device/rearports.html'
  1776. tab = ViewTab(
  1777. label=_('Rear Ports'),
  1778. badge=lambda obj: obj.rear_port_count,
  1779. permission='dcim.view_rearport',
  1780. weight=540,
  1781. hide_if_empty=True
  1782. )
  1783. @register_model_view(Device, 'modulebays', path='module-bays')
  1784. class DeviceModuleBaysView(DeviceComponentsView):
  1785. child_model = ModuleBay
  1786. table = tables.DeviceModuleBayTable
  1787. filterset = filtersets.ModuleBayFilterSet
  1788. filterset_form = forms.ModuleBayFilterForm
  1789. template_name = 'dcim/device/modulebays.html'
  1790. actions = {
  1791. **DEFAULT_ACTION_PERMISSIONS,
  1792. 'bulk_rename': {'change'},
  1793. }
  1794. tab = ViewTab(
  1795. label=_('Module Bays'),
  1796. badge=lambda obj: obj.module_bay_count,
  1797. permission='dcim.view_modulebay',
  1798. weight=510,
  1799. hide_if_empty=True
  1800. )
  1801. @register_model_view(Device, 'devicebays', path='device-bays')
  1802. class DeviceDeviceBaysView(DeviceComponentsView):
  1803. child_model = DeviceBay
  1804. table = tables.DeviceDeviceBayTable
  1805. filterset = filtersets.DeviceBayFilterSet
  1806. filterset_form = forms.DeviceBayFilterForm
  1807. template_name = 'dcim/device/devicebays.html'
  1808. actions = {
  1809. **DEFAULT_ACTION_PERMISSIONS,
  1810. 'bulk_rename': {'change'},
  1811. }
  1812. tab = ViewTab(
  1813. label=_('Device Bays'),
  1814. badge=lambda obj: obj.device_bay_count,
  1815. permission='dcim.view_devicebay',
  1816. weight=500,
  1817. hide_if_empty=True
  1818. )
  1819. @register_model_view(Device, 'inventory')
  1820. class DeviceInventoryView(DeviceComponentsView):
  1821. child_model = InventoryItem
  1822. table = tables.DeviceInventoryItemTable
  1823. filterset = filtersets.InventoryItemFilterSet
  1824. filterset_form = forms.InventoryItemFilterForm
  1825. template_name = 'dcim/device/inventory.html'
  1826. actions = {
  1827. **DEFAULT_ACTION_PERMISSIONS,
  1828. 'bulk_rename': {'change'},
  1829. }
  1830. tab = ViewTab(
  1831. label=_('Inventory Items'),
  1832. badge=lambda obj: obj.inventory_item_count,
  1833. permission='dcim.view_inventoryitem',
  1834. weight=590,
  1835. hide_if_empty=True
  1836. )
  1837. @register_model_view(Device, 'configcontext', path='config-context')
  1838. class DeviceConfigContextView(ObjectConfigContextView):
  1839. queryset = Device.objects.annotate_config_context_data()
  1840. base_template = 'dcim/device/base.html'
  1841. tab = ViewTab(
  1842. label=_('Config Context'),
  1843. weight=2000
  1844. )
  1845. @register_model_view(Device, 'render-config')
  1846. class DeviceRenderConfigView(ObjectRenderConfigView):
  1847. queryset = Device.objects.all()
  1848. base_template = 'dcim/device/base.html'
  1849. tab = ViewTab(
  1850. label=_('Render Config'),
  1851. weight=2100,
  1852. )
  1853. @register_model_view(Device, 'virtual-machines')
  1854. class DeviceVirtualMachinesView(generic.ObjectChildrenView):
  1855. queryset = Device.objects.all()
  1856. child_model = VirtualMachine
  1857. table = VirtualMachineTable
  1858. filterset = VirtualMachineFilterSet
  1859. filterset_form = VirtualMachineFilterForm
  1860. tab = ViewTab(
  1861. label=_('Virtual Machines'),
  1862. badge=lambda obj: VirtualMachine.objects.filter(cluster=obj.cluster, device=obj).count(),
  1863. weight=2200,
  1864. hide_if_empty=True,
  1865. permission='virtualization.view_virtualmachine'
  1866. )
  1867. def get_children(self, request, parent):
  1868. return self.child_model.objects.restrict(request.user, 'view').filter(cluster=parent.cluster, device=parent)
  1869. @register_model_view(Device, 'bulk_import', detail=False)
  1870. class DeviceBulkImportView(generic.BulkImportView):
  1871. queryset = Device.objects.all()
  1872. model_form = forms.DeviceImportForm
  1873. def save_object(self, object_form, request):
  1874. obj = object_form.save()
  1875. # For child devices, save the reverse relation to the parent device bay
  1876. if getattr(obj, 'parent_bay', None):
  1877. device_bay = obj.parent_bay
  1878. device_bay.installed_device = obj
  1879. device_bay.save()
  1880. return obj
  1881. @register_model_view(Device, 'bulk_edit', path='edit', detail=False)
  1882. class DeviceBulkEditView(generic.BulkEditView):
  1883. queryset = Device.objects.prefetch_related('device_type__manufacturer')
  1884. filterset = filtersets.DeviceFilterSet
  1885. table = tables.DeviceTable
  1886. form = forms.DeviceBulkEditForm
  1887. @register_model_view(Device, 'bulk_delete', path='delete', detail=False)
  1888. class DeviceBulkDeleteView(generic.BulkDeleteView):
  1889. queryset = Device.objects.prefetch_related('device_type__manufacturer')
  1890. filterset = filtersets.DeviceFilterSet
  1891. table = tables.DeviceTable
  1892. @register_model_view(Device, 'bulk_rename', path='rename', detail=False)
  1893. class DeviceBulkRenameView(generic.BulkRenameView):
  1894. queryset = Device.objects.all()
  1895. filterset = filtersets.DeviceFilterSet
  1896. table = tables.DeviceTable
  1897. #
  1898. # Modules
  1899. #
  1900. @register_model_view(Module, 'list', path='', detail=False)
  1901. class ModuleListView(generic.ObjectListView):
  1902. queryset = Module.objects.prefetch_related('module_type__manufacturer')
  1903. filterset = filtersets.ModuleFilterSet
  1904. filterset_form = forms.ModuleFilterForm
  1905. table = tables.ModuleTable
  1906. @register_model_view(Module)
  1907. class ModuleView(GetRelatedModelsMixin, generic.ObjectView):
  1908. queryset = Module.objects.all()
  1909. def get_extra_context(self, request, instance):
  1910. return {
  1911. 'related_models': self.get_related_models(request, instance),
  1912. }
  1913. @register_model_view(Module, 'add', detail=False)
  1914. @register_model_view(Module, 'edit')
  1915. class ModuleEditView(generic.ObjectEditView):
  1916. queryset = Module.objects.all()
  1917. form = forms.ModuleForm
  1918. @register_model_view(Module, 'delete')
  1919. class ModuleDeleteView(generic.ObjectDeleteView):
  1920. queryset = Module.objects.all()
  1921. @register_model_view(Module, 'bulk_import', detail=False)
  1922. class ModuleBulkImportView(generic.BulkImportView):
  1923. queryset = Module.objects.all()
  1924. model_form = forms.ModuleImportForm
  1925. @register_model_view(Module, 'bulk_edit', path='edit', detail=False)
  1926. class ModuleBulkEditView(generic.BulkEditView):
  1927. queryset = Module.objects.prefetch_related('module_type__manufacturer')
  1928. filterset = filtersets.ModuleFilterSet
  1929. table = tables.ModuleTable
  1930. form = forms.ModuleBulkEditForm
  1931. @register_model_view(Module, 'bulk_delete', path='delete', detail=False)
  1932. class ModuleBulkDeleteView(generic.BulkDeleteView):
  1933. queryset = Module.objects.prefetch_related('module_type__manufacturer')
  1934. filterset = filtersets.ModuleFilterSet
  1935. table = tables.ModuleTable
  1936. #
  1937. # Console ports
  1938. #
  1939. @register_model_view(ConsolePort, 'list', path='', detail=False)
  1940. class ConsolePortListView(generic.ObjectListView):
  1941. queryset = ConsolePort.objects.all()
  1942. filterset = filtersets.ConsolePortFilterSet
  1943. filterset_form = forms.ConsolePortFilterForm
  1944. table = tables.ConsolePortTable
  1945. template_name = 'dcim/component_list.html'
  1946. actions = {
  1947. **DEFAULT_ACTION_PERMISSIONS,
  1948. 'bulk_rename': {'change'},
  1949. }
  1950. @register_model_view(ConsolePort)
  1951. class ConsolePortView(generic.ObjectView):
  1952. queryset = ConsolePort.objects.all()
  1953. @register_model_view(ConsolePort, 'add', detail=False)
  1954. class ConsolePortCreateView(generic.ComponentCreateView):
  1955. queryset = ConsolePort.objects.all()
  1956. form = forms.ConsolePortCreateForm
  1957. model_form = forms.ConsolePortForm
  1958. @register_model_view(ConsolePort, 'edit')
  1959. class ConsolePortEditView(generic.ObjectEditView):
  1960. queryset = ConsolePort.objects.all()
  1961. form = forms.ConsolePortForm
  1962. @register_model_view(ConsolePort, 'delete')
  1963. class ConsolePortDeleteView(generic.ObjectDeleteView):
  1964. queryset = ConsolePort.objects.all()
  1965. @register_model_view(ConsolePort, 'bulk_import', detail=False)
  1966. class ConsolePortBulkImportView(generic.BulkImportView):
  1967. queryset = ConsolePort.objects.all()
  1968. model_form = forms.ConsolePortImportForm
  1969. @register_model_view(ConsolePort, 'bulk_edit', path='edit', detail=False)
  1970. class ConsolePortBulkEditView(generic.BulkEditView):
  1971. queryset = ConsolePort.objects.all()
  1972. filterset = filtersets.ConsolePortFilterSet
  1973. table = tables.ConsolePortTable
  1974. form = forms.ConsolePortBulkEditForm
  1975. @register_model_view(ConsolePort, 'bulk_rename', path='rename', detail=False)
  1976. class ConsolePortBulkRenameView(generic.BulkRenameView):
  1977. queryset = ConsolePort.objects.all()
  1978. @register_model_view(ConsolePort, 'bulk_disconnect', path='disconnect', detail=False)
  1979. class ConsolePortBulkDisconnectView(BulkDisconnectView):
  1980. queryset = ConsolePort.objects.all()
  1981. @register_model_view(ConsolePort, 'bulk_delete', path='delete', detail=False)
  1982. class ConsolePortBulkDeleteView(generic.BulkDeleteView):
  1983. queryset = ConsolePort.objects.all()
  1984. filterset = filtersets.ConsolePortFilterSet
  1985. table = tables.ConsolePortTable
  1986. # Trace view
  1987. register_model_view(ConsolePort, 'trace', kwargs={'model': ConsolePort})(PathTraceView)
  1988. #
  1989. # Console server ports
  1990. #
  1991. @register_model_view(ConsoleServerPort, 'list', path='', detail=False)
  1992. class ConsoleServerPortListView(generic.ObjectListView):
  1993. queryset = ConsoleServerPort.objects.all()
  1994. filterset = filtersets.ConsoleServerPortFilterSet
  1995. filterset_form = forms.ConsoleServerPortFilterForm
  1996. table = tables.ConsoleServerPortTable
  1997. template_name = 'dcim/component_list.html'
  1998. actions = {
  1999. **DEFAULT_ACTION_PERMISSIONS,
  2000. 'bulk_rename': {'change'},
  2001. }
  2002. @register_model_view(ConsoleServerPort)
  2003. class ConsoleServerPortView(generic.ObjectView):
  2004. queryset = ConsoleServerPort.objects.all()
  2005. @register_model_view(ConsoleServerPort, 'add', detail=False)
  2006. class ConsoleServerPortCreateView(generic.ComponentCreateView):
  2007. queryset = ConsoleServerPort.objects.all()
  2008. form = forms.ConsoleServerPortCreateForm
  2009. model_form = forms.ConsoleServerPortForm
  2010. @register_model_view(ConsoleServerPort, 'edit')
  2011. class ConsoleServerPortEditView(generic.ObjectEditView):
  2012. queryset = ConsoleServerPort.objects.all()
  2013. form = forms.ConsoleServerPortForm
  2014. @register_model_view(ConsoleServerPort, 'delete')
  2015. class ConsoleServerPortDeleteView(generic.ObjectDeleteView):
  2016. queryset = ConsoleServerPort.objects.all()
  2017. @register_model_view(ConsoleServerPort, 'bulk_import', detail=False)
  2018. class ConsoleServerPortBulkImportView(generic.BulkImportView):
  2019. queryset = ConsoleServerPort.objects.all()
  2020. model_form = forms.ConsoleServerPortImportForm
  2021. @register_model_view(ConsoleServerPort, 'bulk_edit', path='edit', detail=False)
  2022. class ConsoleServerPortBulkEditView(generic.BulkEditView):
  2023. queryset = ConsoleServerPort.objects.all()
  2024. filterset = filtersets.ConsoleServerPortFilterSet
  2025. table = tables.ConsoleServerPortTable
  2026. form = forms.ConsoleServerPortBulkEditForm
  2027. @register_model_view(ConsoleServerPort, 'bulk_rename', path='rename', detail=False)
  2028. class ConsoleServerPortBulkRenameView(generic.BulkRenameView):
  2029. queryset = ConsoleServerPort.objects.all()
  2030. @register_model_view(ConsoleServerPort, 'bulk_disconnect', path='disconnect', detail=False)
  2031. class ConsoleServerPortBulkDisconnectView(BulkDisconnectView):
  2032. queryset = ConsoleServerPort.objects.all()
  2033. @register_model_view(ConsoleServerPort, 'bulk_delete', path='delete', detail=False)
  2034. class ConsoleServerPortBulkDeleteView(generic.BulkDeleteView):
  2035. queryset = ConsoleServerPort.objects.all()
  2036. filterset = filtersets.ConsoleServerPortFilterSet
  2037. table = tables.ConsoleServerPortTable
  2038. # Trace view
  2039. register_model_view(ConsoleServerPort, 'trace', kwargs={'model': ConsoleServerPort})(PathTraceView)
  2040. #
  2041. # Power ports
  2042. #
  2043. @register_model_view(PowerPort, 'list', path='', detail=False)
  2044. class PowerPortListView(generic.ObjectListView):
  2045. queryset = PowerPort.objects.all()
  2046. filterset = filtersets.PowerPortFilterSet
  2047. filterset_form = forms.PowerPortFilterForm
  2048. table = tables.PowerPortTable
  2049. template_name = 'dcim/component_list.html'
  2050. actions = {
  2051. **DEFAULT_ACTION_PERMISSIONS,
  2052. 'bulk_rename': {'change'},
  2053. }
  2054. @register_model_view(PowerPort)
  2055. class PowerPortView(generic.ObjectView):
  2056. queryset = PowerPort.objects.all()
  2057. @register_model_view(PowerPort, 'add', detail=False)
  2058. class PowerPortCreateView(generic.ComponentCreateView):
  2059. queryset = PowerPort.objects.all()
  2060. form = forms.PowerPortCreateForm
  2061. model_form = forms.PowerPortForm
  2062. @register_model_view(PowerPort, 'edit')
  2063. class PowerPortEditView(generic.ObjectEditView):
  2064. queryset = PowerPort.objects.all()
  2065. form = forms.PowerPortForm
  2066. @register_model_view(PowerPort, 'delete')
  2067. class PowerPortDeleteView(generic.ObjectDeleteView):
  2068. queryset = PowerPort.objects.all()
  2069. @register_model_view(PowerPort, 'bulk_import', detail=False)
  2070. class PowerPortBulkImportView(generic.BulkImportView):
  2071. queryset = PowerPort.objects.all()
  2072. model_form = forms.PowerPortImportForm
  2073. @register_model_view(PowerPort, 'bulk_edit', path='edit', detail=False)
  2074. class PowerPortBulkEditView(generic.BulkEditView):
  2075. queryset = PowerPort.objects.all()
  2076. filterset = filtersets.PowerPortFilterSet
  2077. table = tables.PowerPortTable
  2078. form = forms.PowerPortBulkEditForm
  2079. @register_model_view(PowerPort, 'bulk_rename', path='rename', detail=False)
  2080. class PowerPortBulkRenameView(generic.BulkRenameView):
  2081. queryset = PowerPort.objects.all()
  2082. @register_model_view(PowerPort, 'bulk_disconnect', path='disconnect', detail=False)
  2083. class PowerPortBulkDisconnectView(BulkDisconnectView):
  2084. queryset = PowerPort.objects.all()
  2085. @register_model_view(PowerPort, 'bulk_delete', path='delete', detail=False)
  2086. class PowerPortBulkDeleteView(generic.BulkDeleteView):
  2087. queryset = PowerPort.objects.all()
  2088. filterset = filtersets.PowerPortFilterSet
  2089. table = tables.PowerPortTable
  2090. # Trace view
  2091. register_model_view(PowerPort, 'trace', kwargs={'model': PowerPort})(PathTraceView)
  2092. #
  2093. # Power outlets
  2094. #
  2095. @register_model_view(PowerOutlet, 'list', path='', detail=False)
  2096. class PowerOutletListView(generic.ObjectListView):
  2097. queryset = PowerOutlet.objects.all()
  2098. filterset = filtersets.PowerOutletFilterSet
  2099. filterset_form = forms.PowerOutletFilterForm
  2100. table = tables.PowerOutletTable
  2101. template_name = 'dcim/component_list.html'
  2102. actions = {
  2103. **DEFAULT_ACTION_PERMISSIONS,
  2104. 'bulk_rename': {'change'},
  2105. }
  2106. @register_model_view(PowerOutlet)
  2107. class PowerOutletView(generic.ObjectView):
  2108. queryset = PowerOutlet.objects.all()
  2109. @register_model_view(PowerOutlet, 'add', detail=False)
  2110. class PowerOutletCreateView(generic.ComponentCreateView):
  2111. queryset = PowerOutlet.objects.all()
  2112. form = forms.PowerOutletCreateForm
  2113. model_form = forms.PowerOutletForm
  2114. @register_model_view(PowerOutlet, 'edit')
  2115. class PowerOutletEditView(generic.ObjectEditView):
  2116. queryset = PowerOutlet.objects.all()
  2117. form = forms.PowerOutletForm
  2118. @register_model_view(PowerOutlet, 'delete')
  2119. class PowerOutletDeleteView(generic.ObjectDeleteView):
  2120. queryset = PowerOutlet.objects.all()
  2121. @register_model_view(PowerOutlet, 'bulk_import', detail=False)
  2122. class PowerOutletBulkImportView(generic.BulkImportView):
  2123. queryset = PowerOutlet.objects.all()
  2124. model_form = forms.PowerOutletImportForm
  2125. @register_model_view(PowerOutlet, 'bulk_edit', path='edit', detail=False)
  2126. class PowerOutletBulkEditView(generic.BulkEditView):
  2127. queryset = PowerOutlet.objects.all()
  2128. filterset = filtersets.PowerOutletFilterSet
  2129. table = tables.PowerOutletTable
  2130. form = forms.PowerOutletBulkEditForm
  2131. @register_model_view(PowerOutlet, 'bulk_rename', path='rename', detail=False)
  2132. class PowerOutletBulkRenameView(generic.BulkRenameView):
  2133. queryset = PowerOutlet.objects.all()
  2134. @register_model_view(PowerOutlet, 'bulk_disconnect', path='disconnect', detail=False)
  2135. class PowerOutletBulkDisconnectView(BulkDisconnectView):
  2136. queryset = PowerOutlet.objects.all()
  2137. @register_model_view(PowerOutlet, 'bulk_delete', path='delete', detail=False)
  2138. class PowerOutletBulkDeleteView(generic.BulkDeleteView):
  2139. queryset = PowerOutlet.objects.all()
  2140. filterset = filtersets.PowerOutletFilterSet
  2141. table = tables.PowerOutletTable
  2142. # Trace view
  2143. register_model_view(PowerOutlet, 'trace', kwargs={'model': PowerOutlet})(PathTraceView)
  2144. #
  2145. # Interfaces
  2146. #
  2147. @register_model_view(Interface, 'list', path='', detail=False)
  2148. class InterfaceListView(generic.ObjectListView):
  2149. queryset = Interface.objects.all()
  2150. filterset = filtersets.InterfaceFilterSet
  2151. filterset_form = forms.InterfaceFilterForm
  2152. table = tables.InterfaceTable
  2153. template_name = 'dcim/component_list.html'
  2154. actions = {
  2155. **DEFAULT_ACTION_PERMISSIONS,
  2156. 'bulk_rename': {'change'},
  2157. }
  2158. @register_model_view(Interface)
  2159. class InterfaceView(generic.ObjectView):
  2160. queryset = Interface.objects.all()
  2161. def get_extra_context(self, request, instance):
  2162. # Get assigned VDCs
  2163. vdc_table = tables.VirtualDeviceContextTable(
  2164. data=instance.vdcs.restrict(request.user, 'view').prefetch_related('device'),
  2165. exclude=(
  2166. 'tenant', 'tenant_group', 'primary_ip', 'primary_ip4', 'primary_ip6', 'oob_ip', 'comments', 'tags',
  2167. 'created', 'last_updated', 'actions',
  2168. ),
  2169. orderable=False
  2170. )
  2171. # Get bridge interfaces
  2172. bridge_interfaces = Interface.objects.restrict(request.user, 'view').filter(bridge=instance)
  2173. bridge_interfaces_table = tables.InterfaceTable(
  2174. bridge_interfaces,
  2175. exclude=('device', 'parent'),
  2176. orderable=False
  2177. )
  2178. # Get child interfaces
  2179. child_interfaces = Interface.objects.restrict(request.user, 'view').filter(parent=instance)
  2180. child_interfaces_table = tables.InterfaceTable(
  2181. child_interfaces,
  2182. exclude=('device', 'parent'),
  2183. orderable=False
  2184. )
  2185. # Get assigned VLANs and annotate whether each is tagged or untagged
  2186. vlans = []
  2187. if instance.untagged_vlan is not None:
  2188. vlans.append(instance.untagged_vlan)
  2189. vlans[0].tagged = False
  2190. for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
  2191. vlan.tagged = True
  2192. vlans.append(vlan)
  2193. vlan_table = InterfaceVLANTable(
  2194. interface=instance,
  2195. data=vlans,
  2196. orderable=False
  2197. )
  2198. # Get VLAN translation rules
  2199. vlan_translation_table = None
  2200. if instance.vlan_translation_policy:
  2201. vlan_translation_table = VLANTranslationRuleTable(
  2202. data=instance.vlan_translation_policy.rules.all(),
  2203. orderable=False
  2204. )
  2205. return {
  2206. 'vdc_table': vdc_table,
  2207. 'bridge_interfaces_table': bridge_interfaces_table,
  2208. 'child_interfaces_table': child_interfaces_table,
  2209. 'vlan_table': vlan_table,
  2210. 'vlan_translation_table': vlan_translation_table,
  2211. }
  2212. @register_model_view(Interface, 'add', detail=False)
  2213. class InterfaceCreateView(generic.ComponentCreateView):
  2214. queryset = Interface.objects.all()
  2215. form = forms.InterfaceCreateForm
  2216. model_form = forms.InterfaceForm
  2217. @register_model_view(Interface, 'edit')
  2218. class InterfaceEditView(generic.ObjectEditView):
  2219. queryset = Interface.objects.all()
  2220. form = forms.InterfaceForm
  2221. @register_model_view(Interface, 'delete')
  2222. class InterfaceDeleteView(generic.ObjectDeleteView):
  2223. queryset = Interface.objects.all()
  2224. @register_model_view(Interface, 'bulk_import', detail=False)
  2225. class InterfaceBulkImportView(generic.BulkImportView):
  2226. queryset = Interface.objects.all()
  2227. model_form = forms.InterfaceImportForm
  2228. @register_model_view(Interface, 'bulk_edit', path='edit', detail=False)
  2229. class InterfaceBulkEditView(generic.BulkEditView):
  2230. queryset = Interface.objects.all()
  2231. filterset = filtersets.InterfaceFilterSet
  2232. table = tables.InterfaceTable
  2233. form = forms.InterfaceBulkEditForm
  2234. def post_save_operations(self, form, obj):
  2235. super().post_save_operations(form, obj)
  2236. # Add/remove tagged VLANs
  2237. if obj.mode == InterfaceModeChoices.MODE_TAGGED:
  2238. if form.cleaned_data.get('add_tagged_vlans', None):
  2239. obj.tagged_vlans.add(*form.cleaned_data['add_tagged_vlans'])
  2240. if form.cleaned_data.get('remove_tagged_vlans', None):
  2241. obj.tagged_vlans.remove(*form.cleaned_data['remove_tagged_vlans'])
  2242. @register_model_view(Interface, 'bulk_rename', path='rename', detail=False)
  2243. class InterfaceBulkRenameView(generic.BulkRenameView):
  2244. queryset = Interface.objects.all()
  2245. @register_model_view(Interface, 'bulk_disconnect', path='disconnect', detail=False)
  2246. class InterfaceBulkDisconnectView(BulkDisconnectView):
  2247. queryset = Interface.objects.all()
  2248. @register_model_view(Interface, 'bulk_delete', path='delete', detail=False)
  2249. class InterfaceBulkDeleteView(generic.BulkDeleteView):
  2250. # Ensure child interfaces are deleted prior to their parents
  2251. queryset = Interface.objects.order_by('device', 'parent', CollateAsChar('_name'))
  2252. filterset = filtersets.InterfaceFilterSet
  2253. table = tables.InterfaceTable
  2254. # Trace view
  2255. register_model_view(Interface, 'trace', kwargs={'model': Interface})(PathTraceView)
  2256. #
  2257. # Front ports
  2258. #
  2259. @register_model_view(FrontPort, 'list', path='', detail=False)
  2260. class FrontPortListView(generic.ObjectListView):
  2261. queryset = FrontPort.objects.all()
  2262. filterset = filtersets.FrontPortFilterSet
  2263. filterset_form = forms.FrontPortFilterForm
  2264. table = tables.FrontPortTable
  2265. template_name = 'dcim/component_list.html'
  2266. actions = {
  2267. **DEFAULT_ACTION_PERMISSIONS,
  2268. 'bulk_rename': {'change'},
  2269. }
  2270. @register_model_view(FrontPort)
  2271. class FrontPortView(generic.ObjectView):
  2272. queryset = FrontPort.objects.all()
  2273. @register_model_view(FrontPort, 'add', detail=False)
  2274. class FrontPortCreateView(generic.ComponentCreateView):
  2275. queryset = FrontPort.objects.all()
  2276. form = forms.FrontPortCreateForm
  2277. model_form = forms.FrontPortForm
  2278. @register_model_view(FrontPort, 'edit')
  2279. class FrontPortEditView(generic.ObjectEditView):
  2280. queryset = FrontPort.objects.all()
  2281. form = forms.FrontPortForm
  2282. @register_model_view(FrontPort, 'delete')
  2283. class FrontPortDeleteView(generic.ObjectDeleteView):
  2284. queryset = FrontPort.objects.all()
  2285. @register_model_view(FrontPort, 'bulk_import', detail=False)
  2286. class FrontPortBulkImportView(generic.BulkImportView):
  2287. queryset = FrontPort.objects.all()
  2288. model_form = forms.FrontPortImportForm
  2289. @register_model_view(FrontPort, 'bulk_edit', path='edit', detail=False)
  2290. class FrontPortBulkEditView(generic.BulkEditView):
  2291. queryset = FrontPort.objects.all()
  2292. filterset = filtersets.FrontPortFilterSet
  2293. table = tables.FrontPortTable
  2294. form = forms.FrontPortBulkEditForm
  2295. @register_model_view(FrontPort, 'bulk_rename', path='rename', detail=False)
  2296. class FrontPortBulkRenameView(generic.BulkRenameView):
  2297. queryset = FrontPort.objects.all()
  2298. @register_model_view(FrontPort, 'bulk_disconnect', path='disconnect', detail=False)
  2299. class FrontPortBulkDisconnectView(BulkDisconnectView):
  2300. queryset = FrontPort.objects.all()
  2301. @register_model_view(FrontPort, 'bulk_delete', path='delete', detail=False)
  2302. class FrontPortBulkDeleteView(generic.BulkDeleteView):
  2303. queryset = FrontPort.objects.all()
  2304. filterset = filtersets.FrontPortFilterSet
  2305. table = tables.FrontPortTable
  2306. # Trace view
  2307. register_model_view(FrontPort, 'trace', kwargs={'model': FrontPort})(PathTraceView)
  2308. #
  2309. # Rear ports
  2310. #
  2311. @register_model_view(RearPort, 'list', path='', detail=False)
  2312. class RearPortListView(generic.ObjectListView):
  2313. queryset = RearPort.objects.all()
  2314. filterset = filtersets.RearPortFilterSet
  2315. filterset_form = forms.RearPortFilterForm
  2316. table = tables.RearPortTable
  2317. template_name = 'dcim/component_list.html'
  2318. actions = {
  2319. **DEFAULT_ACTION_PERMISSIONS,
  2320. 'bulk_rename': {'change'},
  2321. }
  2322. @register_model_view(RearPort)
  2323. class RearPortView(generic.ObjectView):
  2324. queryset = RearPort.objects.all()
  2325. @register_model_view(RearPort, 'add', detail=False)
  2326. class RearPortCreateView(generic.ComponentCreateView):
  2327. queryset = RearPort.objects.all()
  2328. form = forms.RearPortCreateForm
  2329. model_form = forms.RearPortForm
  2330. @register_model_view(RearPort, 'edit')
  2331. class RearPortEditView(generic.ObjectEditView):
  2332. queryset = RearPort.objects.all()
  2333. form = forms.RearPortForm
  2334. @register_model_view(RearPort, 'delete')
  2335. class RearPortDeleteView(generic.ObjectDeleteView):
  2336. queryset = RearPort.objects.all()
  2337. @register_model_view(RearPort, 'bulk_import', detail=False)
  2338. class RearPortBulkImportView(generic.BulkImportView):
  2339. queryset = RearPort.objects.all()
  2340. model_form = forms.RearPortImportForm
  2341. @register_model_view(RearPort, 'bulk_edit', path='edit', detail=False)
  2342. class RearPortBulkEditView(generic.BulkEditView):
  2343. queryset = RearPort.objects.all()
  2344. filterset = filtersets.RearPortFilterSet
  2345. table = tables.RearPortTable
  2346. form = forms.RearPortBulkEditForm
  2347. @register_model_view(RearPort, 'bulk_rename', path='rename', detail=False)
  2348. class RearPortBulkRenameView(generic.BulkRenameView):
  2349. queryset = RearPort.objects.all()
  2350. @register_model_view(RearPort, 'bulk_disconnect', path='disconnect', detail=False)
  2351. class RearPortBulkDisconnectView(BulkDisconnectView):
  2352. queryset = RearPort.objects.all()
  2353. @register_model_view(RearPort, 'bulk_delete', path='delete', detail=False)
  2354. class RearPortBulkDeleteView(generic.BulkDeleteView):
  2355. queryset = RearPort.objects.all()
  2356. filterset = filtersets.RearPortFilterSet
  2357. table = tables.RearPortTable
  2358. # Trace view
  2359. register_model_view(RearPort, 'trace', kwargs={'model': RearPort})(PathTraceView)
  2360. #
  2361. # Module bays
  2362. #
  2363. @register_model_view(ModuleBay, 'list', path='', detail=False)
  2364. class ModuleBayListView(generic.ObjectListView):
  2365. queryset = ModuleBay.objects.select_related('installed_module__module_type')
  2366. filterset = filtersets.ModuleBayFilterSet
  2367. filterset_form = forms.ModuleBayFilterForm
  2368. table = tables.ModuleBayTable
  2369. template_name = 'dcim/component_list.html'
  2370. actions = {
  2371. **DEFAULT_ACTION_PERMISSIONS,
  2372. 'bulk_rename': {'change'},
  2373. }
  2374. @register_model_view(ModuleBay)
  2375. class ModuleBayView(generic.ObjectView):
  2376. queryset = ModuleBay.objects.all()
  2377. @register_model_view(ModuleBay, 'add', detail=False)
  2378. class ModuleBayCreateView(generic.ComponentCreateView):
  2379. queryset = ModuleBay.objects.all()
  2380. form = forms.ModuleBayCreateForm
  2381. model_form = forms.ModuleBayForm
  2382. @register_model_view(ModuleBay, 'edit')
  2383. class ModuleBayEditView(generic.ObjectEditView):
  2384. queryset = ModuleBay.objects.all()
  2385. form = forms.ModuleBayForm
  2386. @register_model_view(ModuleBay, 'delete')
  2387. class ModuleBayDeleteView(generic.ObjectDeleteView):
  2388. queryset = ModuleBay.objects.all()
  2389. @register_model_view(ModuleBay, 'bulk_import', detail=False)
  2390. class ModuleBayBulkImportView(generic.BulkImportView):
  2391. queryset = ModuleBay.objects.all()
  2392. model_form = forms.ModuleBayImportForm
  2393. @register_model_view(ModuleBay, 'bulk_edit', path='edit', detail=False)
  2394. class ModuleBayBulkEditView(generic.BulkEditView):
  2395. queryset = ModuleBay.objects.all()
  2396. filterset = filtersets.ModuleBayFilterSet
  2397. table = tables.ModuleBayTable
  2398. form = forms.ModuleBayBulkEditForm
  2399. @register_model_view(ModuleBay, 'bulk_rename', path='rename', detail=False)
  2400. class ModuleBayBulkRenameView(generic.BulkRenameView):
  2401. queryset = ModuleBay.objects.all()
  2402. @register_model_view(ModuleBay, 'bulk_delete', path='delete', detail=False)
  2403. class ModuleBayBulkDeleteView(generic.BulkDeleteView):
  2404. queryset = ModuleBay.objects.all()
  2405. filterset = filtersets.ModuleBayFilterSet
  2406. table = tables.ModuleBayTable
  2407. #
  2408. # Device bays
  2409. #
  2410. @register_model_view(DeviceBay, 'list', path='', detail=False)
  2411. class DeviceBayListView(generic.ObjectListView):
  2412. queryset = DeviceBay.objects.all()
  2413. filterset = filtersets.DeviceBayFilterSet
  2414. filterset_form = forms.DeviceBayFilterForm
  2415. table = tables.DeviceBayTable
  2416. template_name = 'dcim/component_list.html'
  2417. actions = {
  2418. **DEFAULT_ACTION_PERMISSIONS,
  2419. 'bulk_rename': {'change'},
  2420. }
  2421. @register_model_view(DeviceBay)
  2422. class DeviceBayView(generic.ObjectView):
  2423. queryset = DeviceBay.objects.all()
  2424. @register_model_view(DeviceBay, 'add', detail=False)
  2425. class DeviceBayCreateView(generic.ComponentCreateView):
  2426. queryset = DeviceBay.objects.all()
  2427. form = forms.DeviceBayCreateForm
  2428. model_form = forms.DeviceBayForm
  2429. @register_model_view(DeviceBay, 'edit')
  2430. class DeviceBayEditView(generic.ObjectEditView):
  2431. queryset = DeviceBay.objects.all()
  2432. form = forms.DeviceBayForm
  2433. @register_model_view(DeviceBay, 'delete')
  2434. class DeviceBayDeleteView(generic.ObjectDeleteView):
  2435. queryset = DeviceBay.objects.all()
  2436. @register_model_view(DeviceBay, 'populate')
  2437. class DeviceBayPopulateView(generic.ObjectEditView):
  2438. queryset = DeviceBay.objects.all()
  2439. def get(self, request, pk):
  2440. device_bay = get_object_or_404(self.queryset, pk=pk)
  2441. form = forms.PopulateDeviceBayForm(device_bay)
  2442. return render(request, 'dcim/devicebay_populate.html', {
  2443. 'device_bay': device_bay,
  2444. 'form': form,
  2445. 'return_url': self.get_return_url(request, device_bay),
  2446. })
  2447. def post(self, request, pk):
  2448. device_bay = get_object_or_404(self.queryset, pk=pk)
  2449. form = forms.PopulateDeviceBayForm(device_bay, request.POST)
  2450. if form.is_valid():
  2451. device_bay.snapshot()
  2452. device_bay.installed_device = form.cleaned_data['installed_device']
  2453. device_bay.save()
  2454. messages.success(
  2455. request,
  2456. _("Installed device {device} in bay {device_bay}.").format(
  2457. device=device_bay.installed_device,
  2458. device_bay=device_bay
  2459. )
  2460. )
  2461. return_url = self.get_return_url(request)
  2462. return redirect(return_url)
  2463. return render(request, 'dcim/devicebay_populate.html', {
  2464. 'device_bay': device_bay,
  2465. 'form': form,
  2466. 'return_url': self.get_return_url(request, device_bay),
  2467. })
  2468. @register_model_view(DeviceBay, 'depopulate')
  2469. class DeviceBayDepopulateView(generic.ObjectEditView):
  2470. queryset = DeviceBay.objects.all()
  2471. def get(self, request, pk):
  2472. device_bay = get_object_or_404(self.queryset, pk=pk)
  2473. form = ConfirmationForm()
  2474. return render(request, 'dcim/devicebay_depopulate.html', {
  2475. 'device_bay': device_bay,
  2476. 'form': form,
  2477. 'return_url': self.get_return_url(request, device_bay),
  2478. })
  2479. def post(self, request, pk):
  2480. device_bay = get_object_or_404(self.queryset, pk=pk)
  2481. form = ConfirmationForm(request.POST)
  2482. if form.is_valid():
  2483. device_bay.snapshot()
  2484. removed_device = device_bay.installed_device
  2485. device_bay.installed_device = None
  2486. device_bay.save()
  2487. messages.success(
  2488. request,
  2489. _("Removed device {device} from bay {device_bay}.").format(
  2490. device=removed_device,
  2491. device_bay=device_bay
  2492. )
  2493. )
  2494. return_url = self.get_return_url(request, device_bay.device)
  2495. return redirect(return_url)
  2496. return render(request, 'dcim/devicebay_depopulate.html', {
  2497. 'device_bay': device_bay,
  2498. 'form': form,
  2499. 'return_url': self.get_return_url(request, device_bay),
  2500. })
  2501. @register_model_view(DeviceBay, 'bulk_import', detail=False)
  2502. class DeviceBayBulkImportView(generic.BulkImportView):
  2503. queryset = DeviceBay.objects.all()
  2504. model_form = forms.DeviceBayImportForm
  2505. @register_model_view(DeviceBay, 'bulk_edit', path='edit', detail=False)
  2506. class DeviceBayBulkEditView(generic.BulkEditView):
  2507. queryset = DeviceBay.objects.all()
  2508. filterset = filtersets.DeviceBayFilterSet
  2509. table = tables.DeviceBayTable
  2510. form = forms.DeviceBayBulkEditForm
  2511. @register_model_view(DeviceBay, 'bulk_rename', path='rename', detail=False)
  2512. class DeviceBayBulkRenameView(generic.BulkRenameView):
  2513. queryset = DeviceBay.objects.all()
  2514. @register_model_view(DeviceBay, 'bulk_delete', path='delete', detail=False)
  2515. class DeviceBayBulkDeleteView(generic.BulkDeleteView):
  2516. queryset = DeviceBay.objects.all()
  2517. filterset = filtersets.DeviceBayFilterSet
  2518. table = tables.DeviceBayTable
  2519. #
  2520. # Inventory items
  2521. #
  2522. @register_model_view(InventoryItem, 'list', path='', detail=False)
  2523. class InventoryItemListView(generic.ObjectListView):
  2524. queryset = InventoryItem.objects.all()
  2525. filterset = filtersets.InventoryItemFilterSet
  2526. filterset_form = forms.InventoryItemFilterForm
  2527. table = tables.InventoryItemTable
  2528. template_name = 'dcim/component_list.html'
  2529. actions = {
  2530. **DEFAULT_ACTION_PERMISSIONS,
  2531. 'bulk_rename': {'change'},
  2532. }
  2533. @register_model_view(InventoryItem)
  2534. class InventoryItemView(generic.ObjectView):
  2535. queryset = InventoryItem.objects.all()
  2536. @register_model_view(InventoryItem, 'edit')
  2537. class InventoryItemEditView(generic.ObjectEditView):
  2538. queryset = InventoryItem.objects.all()
  2539. form = forms.InventoryItemForm
  2540. @register_model_view(InventoryItem, 'add', detail=False)
  2541. class InventoryItemCreateView(generic.ComponentCreateView):
  2542. queryset = InventoryItem.objects.all()
  2543. form = forms.InventoryItemCreateForm
  2544. model_form = forms.InventoryItemForm
  2545. @register_model_view(InventoryItem, 'delete')
  2546. class InventoryItemDeleteView(generic.ObjectDeleteView):
  2547. queryset = InventoryItem.objects.all()
  2548. @register_model_view(InventoryItem, 'bulk_import', detail=False)
  2549. class InventoryItemBulkImportView(generic.BulkImportView):
  2550. queryset = InventoryItem.objects.all()
  2551. model_form = forms.InventoryItemImportForm
  2552. @register_model_view(InventoryItem, 'bulk_edit', path='edit', detail=False)
  2553. class InventoryItemBulkEditView(generic.BulkEditView):
  2554. queryset = InventoryItem.objects.all()
  2555. filterset = filtersets.InventoryItemFilterSet
  2556. table = tables.InventoryItemTable
  2557. form = forms.InventoryItemBulkEditForm
  2558. @register_model_view(InventoryItem, 'bulk_rename', path='rename', detail=False)
  2559. class InventoryItemBulkRenameView(generic.BulkRenameView):
  2560. queryset = InventoryItem.objects.all()
  2561. @register_model_view(InventoryItem, 'bulk_delete', path='delete', detail=False)
  2562. class InventoryItemBulkDeleteView(generic.BulkDeleteView):
  2563. queryset = InventoryItem.objects.all()
  2564. filterset = filtersets.InventoryItemFilterSet
  2565. table = tables.InventoryItemTable
  2566. @register_model_view(InventoryItem, 'children')
  2567. class InventoryItemChildrenView(generic.ObjectChildrenView):
  2568. queryset = InventoryItem.objects.all()
  2569. child_model = InventoryItem
  2570. table = tables.InventoryItemTable
  2571. filterset = filtersets.InventoryItemFilterSet
  2572. filterset_form = forms.InventoryItemFilterForm
  2573. tab = ViewTab(
  2574. label=_('Children'),
  2575. badge=lambda obj: obj.child_items.count(),
  2576. permission='dcim.view_inventoryitem',
  2577. hide_if_empty=True,
  2578. weight=5000
  2579. )
  2580. def get_children(self, request, parent):
  2581. return parent.child_items.restrict(request.user, 'view')
  2582. #
  2583. # Inventory item roles
  2584. #
  2585. @register_model_view(InventoryItemRole, 'list', path='', detail=False)
  2586. class InventoryItemRoleListView(generic.ObjectListView):
  2587. queryset = InventoryItemRole.objects.annotate(
  2588. inventoryitem_count=count_related(InventoryItem, 'role'),
  2589. )
  2590. filterset = filtersets.InventoryItemRoleFilterSet
  2591. filterset_form = forms.InventoryItemRoleFilterForm
  2592. table = tables.InventoryItemRoleTable
  2593. @register_model_view(InventoryItemRole)
  2594. class InventoryItemRoleView(generic.ObjectView):
  2595. queryset = InventoryItemRole.objects.all()
  2596. def get_extra_context(self, request, instance):
  2597. return {
  2598. 'inventoryitem_count': InventoryItem.objects.filter(role=instance).count(),
  2599. }
  2600. @register_model_view(InventoryItemRole, 'add', detail=False)
  2601. @register_model_view(InventoryItemRole, 'edit')
  2602. class InventoryItemRoleEditView(generic.ObjectEditView):
  2603. queryset = InventoryItemRole.objects.all()
  2604. form = forms.InventoryItemRoleForm
  2605. @register_model_view(InventoryItemRole, 'delete')
  2606. class InventoryItemRoleDeleteView(generic.ObjectDeleteView):
  2607. queryset = InventoryItemRole.objects.all()
  2608. @register_model_view(InventoryItemRole, 'bulk_import', detail=False)
  2609. class InventoryItemRoleBulkImportView(generic.BulkImportView):
  2610. queryset = InventoryItemRole.objects.all()
  2611. model_form = forms.InventoryItemRoleImportForm
  2612. @register_model_view(InventoryItemRole, 'bulk_edit', path='edit', detail=False)
  2613. class InventoryItemRoleBulkEditView(generic.BulkEditView):
  2614. queryset = InventoryItemRole.objects.annotate(
  2615. inventoryitem_count=count_related(InventoryItem, 'role'),
  2616. )
  2617. filterset = filtersets.InventoryItemRoleFilterSet
  2618. table = tables.InventoryItemRoleTable
  2619. form = forms.InventoryItemRoleBulkEditForm
  2620. @register_model_view(InventoryItemRole, 'bulk_delete', path='delete', detail=False)
  2621. class InventoryItemRoleBulkDeleteView(generic.BulkDeleteView):
  2622. queryset = InventoryItemRole.objects.annotate(
  2623. inventoryitem_count=count_related(InventoryItem, 'role'),
  2624. )
  2625. filterset = filtersets.InventoryItemRoleFilterSet
  2626. table = tables.InventoryItemRoleTable
  2627. #
  2628. # Bulk Device component creation
  2629. #
  2630. class DeviceBulkAddConsolePortView(generic.BulkComponentCreateView):
  2631. parent_model = Device
  2632. parent_field = 'device'
  2633. form = forms.ConsolePortBulkCreateForm
  2634. queryset = ConsolePort.objects.all()
  2635. model_form = forms.ConsolePortForm
  2636. filterset = filtersets.DeviceFilterSet
  2637. table = tables.DeviceTable
  2638. default_return_url = 'dcim:device_list'
  2639. class DeviceBulkAddConsoleServerPortView(generic.BulkComponentCreateView):
  2640. parent_model = Device
  2641. parent_field = 'device'
  2642. form = forms.ConsoleServerPortBulkCreateForm
  2643. queryset = ConsoleServerPort.objects.all()
  2644. model_form = forms.ConsoleServerPortForm
  2645. filterset = filtersets.DeviceFilterSet
  2646. table = tables.DeviceTable
  2647. default_return_url = 'dcim:device_list'
  2648. class DeviceBulkAddPowerPortView(generic.BulkComponentCreateView):
  2649. parent_model = Device
  2650. parent_field = 'device'
  2651. form = forms.PowerPortBulkCreateForm
  2652. queryset = PowerPort.objects.all()
  2653. model_form = forms.PowerPortForm
  2654. filterset = filtersets.DeviceFilterSet
  2655. table = tables.DeviceTable
  2656. default_return_url = 'dcim:device_list'
  2657. class DeviceBulkAddPowerOutletView(generic.BulkComponentCreateView):
  2658. parent_model = Device
  2659. parent_field = 'device'
  2660. form = forms.PowerOutletBulkCreateForm
  2661. queryset = PowerOutlet.objects.all()
  2662. model_form = forms.PowerOutletForm
  2663. filterset = filtersets.DeviceFilterSet
  2664. table = tables.DeviceTable
  2665. default_return_url = 'dcim:device_list'
  2666. class DeviceBulkAddInterfaceView(generic.BulkComponentCreateView):
  2667. parent_model = Device
  2668. parent_field = 'device'
  2669. form = forms.InterfaceBulkCreateForm
  2670. queryset = Interface.objects.all()
  2671. model_form = forms.InterfaceForm
  2672. filterset = filtersets.DeviceFilterSet
  2673. table = tables.DeviceTable
  2674. default_return_url = 'dcim:device_list'
  2675. class DeviceBulkAddRearPortView(generic.BulkComponentCreateView):
  2676. parent_model = Device
  2677. parent_field = 'device'
  2678. form = forms.RearPortBulkCreateForm
  2679. queryset = RearPort.objects.all()
  2680. model_form = forms.RearPortForm
  2681. filterset = filtersets.DeviceFilterSet
  2682. table = tables.DeviceTable
  2683. default_return_url = 'dcim:device_list'
  2684. class DeviceBulkAddModuleBayView(generic.BulkComponentCreateView):
  2685. parent_model = Device
  2686. parent_field = 'device'
  2687. form = forms.ModuleBayBulkCreateForm
  2688. queryset = ModuleBay.objects.all()
  2689. model_form = forms.ModuleBayForm
  2690. filterset = filtersets.DeviceFilterSet
  2691. table = tables.DeviceTable
  2692. default_return_url = 'dcim:device_list'
  2693. class DeviceBulkAddDeviceBayView(generic.BulkComponentCreateView):
  2694. parent_model = Device
  2695. parent_field = 'device'
  2696. form = forms.DeviceBayBulkCreateForm
  2697. queryset = DeviceBay.objects.all()
  2698. model_form = forms.DeviceBayForm
  2699. filterset = filtersets.DeviceFilterSet
  2700. table = tables.DeviceTable
  2701. default_return_url = 'dcim:device_list'
  2702. class DeviceBulkAddInventoryItemView(generic.BulkComponentCreateView):
  2703. parent_model = Device
  2704. parent_field = 'device'
  2705. form = forms.InventoryItemBulkCreateForm
  2706. queryset = InventoryItem.objects.all()
  2707. model_form = forms.InventoryItemForm
  2708. filterset = filtersets.DeviceFilterSet
  2709. table = tables.DeviceTable
  2710. default_return_url = 'dcim:device_list'
  2711. #
  2712. # Cables
  2713. #
  2714. @register_model_view(Cable, 'list', path='', detail=False)
  2715. class CableListView(generic.ObjectListView):
  2716. queryset = Cable.objects.prefetch_related(
  2717. 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location',
  2718. 'terminations___site',
  2719. )
  2720. filterset = filtersets.CableFilterSet
  2721. filterset_form = forms.CableFilterForm
  2722. table = tables.CableTable
  2723. @register_model_view(Cable)
  2724. class CableView(generic.ObjectView):
  2725. queryset = Cable.objects.all()
  2726. @register_model_view(Cable, 'add', detail=False)
  2727. @register_model_view(Cable, 'edit')
  2728. class CableEditView(generic.ObjectEditView):
  2729. queryset = Cable.objects.all()
  2730. template_name = 'dcim/cable_edit.html'
  2731. htmx_template_name = 'dcim/htmx/cable_edit.html'
  2732. def alter_object(self, obj, request, url_args, url_kwargs):
  2733. """
  2734. Hack into alter_object() to set the form class when editing an existing Cable, since ObjectEditView
  2735. doesn't currently provide a hook for dynamic class resolution.
  2736. """
  2737. a_terminations_type = CABLE_TERMINATION_TYPES.get(
  2738. request.POST.get('a_terminations_type') or request.GET.get('a_terminations_type')
  2739. )
  2740. b_terminations_type = CABLE_TERMINATION_TYPES.get(
  2741. request.POST.get('b_terminations_type') or request.GET.get('b_terminations_type')
  2742. )
  2743. if obj.pk:
  2744. if not a_terminations_type and (termination_a := obj.terminations.filter(cable_end='A').first()):
  2745. a_terminations_type = termination_a.termination._meta.model
  2746. if not b_terminations_type and (termination_b := obj.terminations.filter(cable_end='B').first()):
  2747. b_terminations_type = termination_b.termination._meta.model
  2748. self.form = forms.get_cable_form(a_terminations_type, b_terminations_type)
  2749. return super().alter_object(obj, request, url_args, url_kwargs)
  2750. def get_extra_addanother_params(self, request):
  2751. params = {
  2752. 'a_terminations_type': request.GET.get('a_terminations_type'),
  2753. 'b_terminations_type': request.GET.get('b_terminations_type')
  2754. }
  2755. for key in request.POST:
  2756. if 'device' in key or 'power_panel' in key or 'circuit' in key:
  2757. params.update({key: request.POST.get(key)})
  2758. return params
  2759. @register_model_view(Cable, 'delete')
  2760. class CableDeleteView(generic.ObjectDeleteView):
  2761. queryset = Cable.objects.all()
  2762. @register_model_view(Cable, 'bulk_import', detail=False)
  2763. class CableBulkImportView(generic.BulkImportView):
  2764. queryset = Cable.objects.all()
  2765. model_form = forms.CableImportForm
  2766. @register_model_view(Cable, 'bulk_edit', path='edit', detail=False)
  2767. class CableBulkEditView(generic.BulkEditView):
  2768. queryset = Cable.objects.prefetch_related(
  2769. 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location',
  2770. 'terminations___site',
  2771. )
  2772. filterset = filtersets.CableFilterSet
  2773. table = tables.CableTable
  2774. form = forms.CableBulkEditForm
  2775. @register_model_view(Cable, 'bulk_delete', path='delete', detail=False)
  2776. class CableBulkDeleteView(generic.BulkDeleteView):
  2777. queryset = Cable.objects.prefetch_related(
  2778. 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location',
  2779. 'terminations___site',
  2780. )
  2781. filterset = filtersets.CableFilterSet
  2782. table = tables.CableTable
  2783. #
  2784. # Connections
  2785. #
  2786. class ConsoleConnectionsListView(generic.ObjectListView):
  2787. queryset = ConsolePort.objects.filter(_path__is_complete=True)
  2788. filterset = filtersets.ConsoleConnectionFilterSet
  2789. filterset_form = forms.ConsoleConnectionFilterForm
  2790. table = tables.ConsoleConnectionTable
  2791. template_name = 'dcim/connections_list.html'
  2792. actions = {
  2793. 'export': {'view'},
  2794. }
  2795. def get_extra_context(self, request):
  2796. return {
  2797. 'title': 'Console Connections'
  2798. }
  2799. class PowerConnectionsListView(generic.ObjectListView):
  2800. queryset = PowerPort.objects.filter(_path__is_complete=True)
  2801. filterset = filtersets.PowerConnectionFilterSet
  2802. filterset_form = forms.PowerConnectionFilterForm
  2803. table = tables.PowerConnectionTable
  2804. template_name = 'dcim/connections_list.html'
  2805. actions = {
  2806. 'export': {'view'},
  2807. }
  2808. def get_extra_context(self, request):
  2809. return {
  2810. 'title': 'Power Connections'
  2811. }
  2812. class InterfaceConnectionsListView(generic.ObjectListView):
  2813. queryset = Interface.objects.filter(_path__is_complete=True)
  2814. filterset = filtersets.InterfaceConnectionFilterSet
  2815. filterset_form = forms.InterfaceConnectionFilterForm
  2816. table = tables.InterfaceConnectionTable
  2817. template_name = 'dcim/connections_list.html'
  2818. actions = {
  2819. 'export': {'view'},
  2820. }
  2821. def get_extra_context(self, request):
  2822. return {
  2823. 'title': 'Interface Connections'
  2824. }
  2825. #
  2826. # Virtual chassis
  2827. #
  2828. @register_model_view(VirtualChassis, 'list', path='', detail=False)
  2829. class VirtualChassisListView(generic.ObjectListView):
  2830. queryset = VirtualChassis.objects.all()
  2831. table = tables.VirtualChassisTable
  2832. filterset = filtersets.VirtualChassisFilterSet
  2833. filterset_form = forms.VirtualChassisFilterForm
  2834. @register_model_view(VirtualChassis)
  2835. class VirtualChassisView(generic.ObjectView):
  2836. queryset = VirtualChassis.objects.all()
  2837. def get_extra_context(self, request, instance):
  2838. members = Device.objects.restrict(request.user).filter(virtual_chassis=instance)
  2839. return {
  2840. 'members': members,
  2841. }
  2842. @register_model_view(VirtualChassis, 'add', detail=False)
  2843. class VirtualChassisCreateView(generic.ObjectEditView):
  2844. queryset = VirtualChassis.objects.all()
  2845. form = forms.VirtualChassisCreateForm
  2846. template_name = 'dcim/virtualchassis_add.html'
  2847. @register_model_view(VirtualChassis, 'edit')
  2848. class VirtualChassisEditView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
  2849. queryset = VirtualChassis.objects.all()
  2850. def get_required_permission(self):
  2851. return 'dcim.change_virtualchassis'
  2852. def get(self, request, pk):
  2853. virtual_chassis = get_object_or_404(self.queryset, pk=pk)
  2854. VCMemberFormSet = modelformset_factory(
  2855. model=Device,
  2856. form=forms.DeviceVCMembershipForm,
  2857. formset=forms.BaseVCMemberFormSet,
  2858. extra=0
  2859. )
  2860. members_queryset = virtual_chassis.members.prefetch_related('rack').order_by('vc_position')
  2861. vc_form = forms.VirtualChassisForm(instance=virtual_chassis)
  2862. vc_form.fields['master'].queryset = members_queryset
  2863. formset = VCMemberFormSet(queryset=members_queryset)
  2864. return render(request, 'dcim/virtualchassis_edit.html', {
  2865. 'object': virtual_chassis,
  2866. 'vc_form': vc_form,
  2867. 'formset': formset,
  2868. 'return_url': self.get_return_url(request, virtual_chassis),
  2869. })
  2870. def post(self, request, pk):
  2871. virtual_chassis = get_object_or_404(self.queryset, pk=pk)
  2872. VCMemberFormSet = modelformset_factory(
  2873. model=Device,
  2874. form=forms.DeviceVCMembershipForm,
  2875. formset=forms.BaseVCMemberFormSet,
  2876. extra=0
  2877. )
  2878. members_queryset = virtual_chassis.members.prefetch_related('rack').order_by('vc_position')
  2879. vc_form = forms.VirtualChassisForm(request.POST, instance=virtual_chassis)
  2880. vc_form.fields['master'].queryset = members_queryset
  2881. formset = VCMemberFormSet(request.POST, queryset=members_queryset)
  2882. if vc_form.is_valid() and formset.is_valid():
  2883. with transaction.atomic():
  2884. # Save the VirtualChassis
  2885. vc_form.save()
  2886. # Nullify the vc_position of each member first to allow reordering without raising an IntegrityError on
  2887. # duplicate positions. Then save each member instance.
  2888. members = formset.save(commit=False)
  2889. devices = Device.objects.filter(pk__in=[m.pk for m in members])
  2890. for device in devices:
  2891. device.vc_position = None
  2892. device.save()
  2893. for member in members:
  2894. member.save()
  2895. return redirect(virtual_chassis.get_absolute_url())
  2896. return render(request, 'dcim/virtualchassis_edit.html', {
  2897. 'vc_form': vc_form,
  2898. 'formset': formset,
  2899. 'return_url': self.get_return_url(request, virtual_chassis),
  2900. })
  2901. @register_model_view(VirtualChassis, 'delete')
  2902. class VirtualChassisDeleteView(generic.ObjectDeleteView):
  2903. queryset = VirtualChassis.objects.all()
  2904. @register_model_view(VirtualChassis, 'add_member', path='add-member')
  2905. class VirtualChassisAddMemberView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
  2906. queryset = VirtualChassis.objects.all()
  2907. def get_required_permission(self):
  2908. return 'dcim.change_virtualchassis'
  2909. def get(self, request, pk):
  2910. virtual_chassis = get_object_or_404(self.queryset, pk=pk)
  2911. initial_data = {k: request.GET[k] for k in request.GET}
  2912. member_select_form = forms.VCMemberSelectForm(initial=initial_data)
  2913. membership_form = forms.DeviceVCMembershipForm(initial=initial_data)
  2914. return render(request, 'dcim/virtualchassis_add_member.html', {
  2915. 'virtual_chassis': virtual_chassis,
  2916. 'member_select_form': member_select_form,
  2917. 'membership_form': membership_form,
  2918. 'return_url': self.get_return_url(request, virtual_chassis),
  2919. })
  2920. def post(self, request, pk):
  2921. virtual_chassis = get_object_or_404(self.queryset, pk=pk)
  2922. member_select_form = forms.VCMemberSelectForm(request.POST)
  2923. if member_select_form.is_valid():
  2924. device = member_select_form.cleaned_data['device']
  2925. device.virtual_chassis = virtual_chassis
  2926. data = {k: request.POST[k] for k in ['vc_position', 'vc_priority']}
  2927. membership_form = forms.DeviceVCMembershipForm(data=data, validate_vc_position=True, instance=device)
  2928. if membership_form.is_valid():
  2929. membership_form.save()
  2930. messages.success(request, mark_safe(
  2931. _('Added member <a href="{url}">{device}</a>').format(
  2932. url=device.get_absolute_url(), device=escape(device)
  2933. )
  2934. ))
  2935. if '_addanother' in request.POST:
  2936. return redirect(request.get_full_path())
  2937. return redirect(self.get_return_url(request, device))
  2938. else:
  2939. membership_form = forms.DeviceVCMembershipForm(data=request.POST)
  2940. return render(request, 'dcim/virtualchassis_add_member.html', {
  2941. 'virtual_chassis': virtual_chassis,
  2942. 'member_select_form': member_select_form,
  2943. 'membership_form': membership_form,
  2944. 'return_url': self.get_return_url(request, virtual_chassis),
  2945. })
  2946. class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
  2947. queryset = Device.objects.all()
  2948. def get_required_permission(self):
  2949. return 'dcim.change_device'
  2950. def get(self, request, pk):
  2951. device = get_object_or_404(self.queryset, pk=pk, virtual_chassis__isnull=False)
  2952. form = ConfirmationForm(initial=request.GET)
  2953. return render(request, 'dcim/virtualchassis_remove_member.html', {
  2954. 'device': device,
  2955. 'form': form,
  2956. 'return_url': self.get_return_url(request, device),
  2957. })
  2958. def post(self, request, pk):
  2959. device = get_object_or_404(self.queryset, pk=pk, virtual_chassis__isnull=False)
  2960. form = ConfirmationForm(request.POST)
  2961. # Protect master device from being removed
  2962. virtual_chassis = VirtualChassis.objects.filter(master=device).first()
  2963. if virtual_chassis is not None:
  2964. messages.error(
  2965. request,
  2966. _('Unable to remove master device {device} from the virtual chassis.').format(device=device)
  2967. )
  2968. return redirect(device.get_absolute_url())
  2969. if form.is_valid():
  2970. devices = Device.objects.filter(pk=device.pk)
  2971. for device in devices:
  2972. device.virtual_chassis = None
  2973. device.vc_position = None
  2974. device.vc_priority = None
  2975. device.save()
  2976. msg = _('Removed {device} from virtual chassis {chassis}').format(
  2977. device=device,
  2978. chassis=device.virtual_chassis
  2979. )
  2980. messages.success(request, msg)
  2981. return redirect(self.get_return_url(request, device))
  2982. return render(request, 'dcim/virtualchassis_remove_member.html', {
  2983. 'device': device,
  2984. 'form': form,
  2985. 'return_url': self.get_return_url(request, device),
  2986. })
  2987. @register_model_view(VirtualChassis, 'bulk_import', detail=False)
  2988. class VirtualChassisBulkImportView(generic.BulkImportView):
  2989. queryset = VirtualChassis.objects.all()
  2990. model_form = forms.VirtualChassisImportForm
  2991. @register_model_view(VirtualChassis, 'bulk_edit', path='edit', detail=False)
  2992. class VirtualChassisBulkEditView(generic.BulkEditView):
  2993. queryset = VirtualChassis.objects.all()
  2994. filterset = filtersets.VirtualChassisFilterSet
  2995. table = tables.VirtualChassisTable
  2996. form = forms.VirtualChassisBulkEditForm
  2997. @register_model_view(VirtualChassis, 'bulk_delete', path='delete', detail=False)
  2998. class VirtualChassisBulkDeleteView(generic.BulkDeleteView):
  2999. queryset = VirtualChassis.objects.all()
  3000. filterset = filtersets.VirtualChassisFilterSet
  3001. table = tables.VirtualChassisTable
  3002. #
  3003. # Power panels
  3004. #
  3005. @register_model_view(PowerPanel, 'list', path='', detail=False)
  3006. class PowerPanelListView(generic.ObjectListView):
  3007. queryset = PowerPanel.objects.annotate(
  3008. powerfeed_count=count_related(PowerFeed, 'power_panel')
  3009. )
  3010. filterset = filtersets.PowerPanelFilterSet
  3011. filterset_form = forms.PowerPanelFilterForm
  3012. table = tables.PowerPanelTable
  3013. @register_model_view(PowerPanel)
  3014. class PowerPanelView(GetRelatedModelsMixin, generic.ObjectView):
  3015. queryset = PowerPanel.objects.all()
  3016. def get_extra_context(self, request, instance):
  3017. return {
  3018. 'related_models': self.get_related_models(request, instance),
  3019. }
  3020. @register_model_view(PowerPanel, 'add', detail=False)
  3021. @register_model_view(PowerPanel, 'edit')
  3022. class PowerPanelEditView(generic.ObjectEditView):
  3023. queryset = PowerPanel.objects.all()
  3024. form = forms.PowerPanelForm
  3025. @register_model_view(PowerPanel, 'delete')
  3026. class PowerPanelDeleteView(generic.ObjectDeleteView):
  3027. queryset = PowerPanel.objects.all()
  3028. @register_model_view(PowerPanel, 'bulk_import', detail=False)
  3029. class PowerPanelBulkImportView(generic.BulkImportView):
  3030. queryset = PowerPanel.objects.all()
  3031. model_form = forms.PowerPanelImportForm
  3032. @register_model_view(PowerPanel, 'bulk_edit', path='edit', detail=False)
  3033. class PowerPanelBulkEditView(generic.BulkEditView):
  3034. queryset = PowerPanel.objects.all()
  3035. filterset = filtersets.PowerPanelFilterSet
  3036. table = tables.PowerPanelTable
  3037. form = forms.PowerPanelBulkEditForm
  3038. @register_model_view(PowerPanel, 'bulk_delete', path='delete', detail=False)
  3039. class PowerPanelBulkDeleteView(generic.BulkDeleteView):
  3040. queryset = PowerPanel.objects.annotate(
  3041. powerfeed_count=count_related(PowerFeed, 'power_panel')
  3042. )
  3043. filterset = filtersets.PowerPanelFilterSet
  3044. table = tables.PowerPanelTable
  3045. #
  3046. # Power feeds
  3047. #
  3048. @register_model_view(PowerFeed, 'list', path='', detail=False)
  3049. class PowerFeedListView(generic.ObjectListView):
  3050. queryset = PowerFeed.objects.all()
  3051. filterset = filtersets.PowerFeedFilterSet
  3052. filterset_form = forms.PowerFeedFilterForm
  3053. table = tables.PowerFeedTable
  3054. @register_model_view(PowerFeed)
  3055. class PowerFeedView(generic.ObjectView):
  3056. queryset = PowerFeed.objects.all()
  3057. @register_model_view(PowerFeed, 'add', detail=False)
  3058. @register_model_view(PowerFeed, 'edit')
  3059. class PowerFeedEditView(generic.ObjectEditView):
  3060. queryset = PowerFeed.objects.all()
  3061. form = forms.PowerFeedForm
  3062. @register_model_view(PowerFeed, 'delete')
  3063. class PowerFeedDeleteView(generic.ObjectDeleteView):
  3064. queryset = PowerFeed.objects.all()
  3065. @register_model_view(PowerFeed, 'bulk_import', detail=False)
  3066. class PowerFeedBulkImportView(generic.BulkImportView):
  3067. queryset = PowerFeed.objects.all()
  3068. model_form = forms.PowerFeedImportForm
  3069. @register_model_view(PowerFeed, 'bulk_edit', path='edit', detail=False)
  3070. class PowerFeedBulkEditView(generic.BulkEditView):
  3071. queryset = PowerFeed.objects.all()
  3072. filterset = filtersets.PowerFeedFilterSet
  3073. table = tables.PowerFeedTable
  3074. form = forms.PowerFeedBulkEditForm
  3075. @register_model_view(PowerFeed, 'bulk_disconnect', path='disconnect', detail=False)
  3076. class PowerFeedBulkDisconnectView(BulkDisconnectView):
  3077. queryset = PowerFeed.objects.all()
  3078. @register_model_view(PowerFeed, 'bulk_delete', path='delete', detail=False)
  3079. class PowerFeedBulkDeleteView(generic.BulkDeleteView):
  3080. queryset = PowerFeed.objects.all()
  3081. filterset = filtersets.PowerFeedFilterSet
  3082. table = tables.PowerFeedTable
  3083. # Trace view
  3084. register_model_view(PowerFeed, 'trace', kwargs={'model': PowerFeed})(PathTraceView)
  3085. #
  3086. # Virtual device contexts
  3087. #
  3088. @register_model_view(VirtualDeviceContext, 'list', path='', detail=False)
  3089. class VirtualDeviceContextListView(generic.ObjectListView):
  3090. queryset = VirtualDeviceContext.objects.annotate(
  3091. interface_count=count_related(Interface, 'vdcs'),
  3092. )
  3093. filterset = filtersets.VirtualDeviceContextFilterSet
  3094. filterset_form = forms.VirtualDeviceContextFilterForm
  3095. table = tables.VirtualDeviceContextTable
  3096. @register_model_view(VirtualDeviceContext)
  3097. class VirtualDeviceContextView(GetRelatedModelsMixin, generic.ObjectView):
  3098. queryset = VirtualDeviceContext.objects.all()
  3099. def get_extra_context(self, request, instance):
  3100. return {
  3101. 'related_models': self.get_related_models(
  3102. request,
  3103. instance,
  3104. extra=(
  3105. (Interface.objects.restrict(request.user, 'view').filter(vdcs__in=[instance]), 'vdc_id'),
  3106. ),
  3107. ),
  3108. }
  3109. @register_model_view(VirtualDeviceContext, 'add', detail=False)
  3110. @register_model_view(VirtualDeviceContext, 'edit')
  3111. class VirtualDeviceContextEditView(generic.ObjectEditView):
  3112. queryset = VirtualDeviceContext.objects.all()
  3113. form = forms.VirtualDeviceContextForm
  3114. @register_model_view(VirtualDeviceContext, 'delete')
  3115. class VirtualDeviceContextDeleteView(generic.ObjectDeleteView):
  3116. queryset = VirtualDeviceContext.objects.all()
  3117. @register_model_view(VirtualDeviceContext, 'bulk_import', detail=False)
  3118. class VirtualDeviceContextBulkImportView(generic.BulkImportView):
  3119. queryset = VirtualDeviceContext.objects.all()
  3120. model_form = forms.VirtualDeviceContextImportForm
  3121. @register_model_view(VirtualDeviceContext, 'bulk_edit', path='edit', detail=False)
  3122. class VirtualDeviceContextBulkEditView(generic.BulkEditView):
  3123. queryset = VirtualDeviceContext.objects.all()
  3124. filterset = filtersets.VirtualDeviceContextFilterSet
  3125. table = tables.VirtualDeviceContextTable
  3126. form = forms.VirtualDeviceContextBulkEditForm
  3127. @register_model_view(VirtualDeviceContext, 'bulk_delete', path='delete', detail=False)
  3128. class VirtualDeviceContextBulkDeleteView(generic.BulkDeleteView):
  3129. queryset = VirtualDeviceContext.objects.all()
  3130. filterset = filtersets.VirtualDeviceContextFilterSet
  3131. table = tables.VirtualDeviceContextTable
  3132. #
  3133. # MAC addresses
  3134. #
  3135. @register_model_view(MACAddress, 'list', path='', detail=False)
  3136. class MACAddressListView(generic.ObjectListView):
  3137. queryset = MACAddress.objects.all()
  3138. filterset = filtersets.MACAddressFilterSet
  3139. filterset_form = forms.MACAddressFilterForm
  3140. table = tables.MACAddressTable
  3141. @register_model_view(MACAddress)
  3142. class MACAddressView(generic.ObjectView):
  3143. queryset = MACAddress.objects.all()
  3144. @register_model_view(MACAddress, 'add', detail=False)
  3145. @register_model_view(MACAddress, 'edit')
  3146. class MACAddressEditView(generic.ObjectEditView):
  3147. queryset = MACAddress.objects.all()
  3148. form = forms.MACAddressForm
  3149. @register_model_view(MACAddress, 'delete')
  3150. class MACAddressDeleteView(generic.ObjectDeleteView):
  3151. queryset = MACAddress.objects.all()
  3152. @register_model_view(MACAddress, 'bulk_import', detail=False)
  3153. class MACAddressBulkImportView(generic.BulkImportView):
  3154. queryset = MACAddress.objects.all()
  3155. model_form = forms.MACAddressImportForm
  3156. @register_model_view(MACAddress, 'bulk_edit', path='edit', detail=False)
  3157. class MACAddressBulkEditView(generic.BulkEditView):
  3158. queryset = MACAddress.objects.all()
  3159. filterset = filtersets.MACAddressFilterSet
  3160. table = tables.MACAddressTable
  3161. form = forms.MACAddressBulkEditForm
  3162. @register_model_view(MACAddress, 'bulk_delete', path='delete', detail=False)
  3163. class MACAddressBulkDeleteView(generic.BulkDeleteView):
  3164. queryset = MACAddress.objects.all()
  3165. filterset = filtersets.MACAddressFilterSet
  3166. table = tables.MACAddressTable