feat: network topology diagram with Packet-Tracer-style symbols
- New section "Netzwerk-Topologie": one diagram per site built from NetBox cable paths (traced through patch panels), layered top-down by cabling (provider > firewall/router > core > access > endpoints), barycenter ordering, "2x" for parallel links, provider circuits as clouds and devices outside the scope dashed. Labels: management IP, model, ports. - New export format "draw.io": the topology as an editable .drawio file (one page per site, symbols embedded). - 14 built-in symbols drawn with Pillow; automatic mapping from role, model and manufacturer, passive gear (patch panels, PDUs, UPS) hidden. - New TopologySymbol model (migration 0002) with list/edit/delete UI, symbol gallery, custom icon upload and a "Topologie-Symbol" button on device type and device role pages. Bump version to 0.4.0 - requires "manage.py migrate". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,20 @@ class ScopeSelectView(LoginRequiredMixin, View):
|
||||
|
||||
|
||||
class ExportView(LoginRequiredMixin, View):
|
||||
def _drawio(self, request, scope, form, opts):
|
||||
"""Nur die Topologie – als editierbare draw.io-Datei (eine Seite je Standort)."""
|
||||
from .topology import build_graphs, render_drawio
|
||||
|
||||
graphs = build_graphs(scope, opts)
|
||||
if not graphs:
|
||||
messages.warning(request, "Keine verkabelten Geräte gefunden – es gibt keine Topologie zu exportieren.")
|
||||
return self._render_form(request, scope, form)
|
||||
content = render_drawio(graphs, show_ports="ports" in (opts.get("topo_details") or []))
|
||||
response = HttpResponse(content, content_type="application/xml")
|
||||
filename = f"topologie_{slugify(str(scope.obj)) or 'export'}_{timezone.localdate():%Y%m%d}.drawio"
|
||||
response["Content-Disposition"] = f'attachment; filename="{filename}"'
|
||||
return response
|
||||
|
||||
template_name = "netbox_customer_export/export.html"
|
||||
|
||||
def _scope(self, request, kind, pk):
|
||||
@@ -54,6 +68,8 @@ class ExportView(LoginRequiredMixin, View):
|
||||
return self._render_form(request, scope, form)
|
||||
|
||||
opts = form.cleaned_data
|
||||
if opts["format"] == "drawio":
|
||||
return self._drawio(request, scope, form, opts)
|
||||
blocks = []
|
||||
for key in opts["sections"]:
|
||||
blocks += SECTIONS[key].func(scope, opts)
|
||||
|
||||
Reference in New Issue
Block a user