views.py 141 KB

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