You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何生成带有可拖拽元素的Django Model关系图?

Turn Your Static Django Model Graph into a Draggable, Interactive One

Hey there! Since you already have your .dot file from py manage.py graph_models, we’re halfway there. Turning that static graph into a draggable, interactive version doesn’t have to be complicated—here are three straightforward approaches you can use:

1. Use a JavaScript Graphviz Library (d3-graphviz) for In-Browser Rendering

This method lets you render your .dot file directly in a Django template as an interactive SVG, with built-in drag-and-drop support.

Step-by-Step:

  • First, save your generated .dot file in your Django project’s static directory (e.g., static/graphs/my_models.dot).
  • Download the d3-graphviz library files (and its dependency d3.min.js) and add them to your static/js folder to keep everything local.
  • Create a Django template (e.g., model_graph.html) with the following code:
{% load static %}
<div id="model-graph" style="width: 100%; height: 800px;"></div>

<script src="{% static 'js/d3.min.js' %}"></script>
<script src="{% static 'js/d3-graphviz.min.js' %}"></script>
<script>
  // Fetch the .dot file content
  fetch("{% static 'graphs/my_models.dot' %}")
    .then(response => response.text())
    .then(dotSource => {
      // Render the graph with drag enabled
      d3.select("#model-graph").graphviz()
        .renderDot(dotSource)
        .on("end", () => {
          // Enable dragging for nodes
          d3.selectAll(".node").call(d3.drag()
            .on("drag", function(event) {
              d3.select(this)
                .attr("transform", `translate(${event.x}, ${event.y})`);
            })
          );
        });
    });
</script>
  • Create a simple view to serve this template, and map it to a URL in your urls.py. When you load the page, your model nodes will be fully draggable!

2. Generate an Interactive HTML Graph with PyVis

PyVis is a Python library that creates interactive network graphs as HTML files. It can import your existing .dot file and output a self-contained HTML page with draggable nodes, zoom controls, and hover tooltips.

Step-by-Step:

  • Install PyVis first:
    pip install pyvis
    
  • Create a small Python script (or add this to a Django management command) to process your .dot file:
from pyvis.network import Network

# Load your .dot file
net = Network(height="800px", width="100%", directed=True)
net.from_dot("path/to/your/models.dot")

# Enable drag and other interactive features
net.set_options("""
var options = {
  "interaction": {
    "dragNodes": true,
    "zoomView": true
  }
}
""")

# Save the interactive HTML file
net.write_html("static/graphs/interactive_model_graph.html")
  • Now you can embed this HTML file in your Django template using an <iframe>:
<iframe src="{% static 'graphs/interactive_model_graph.html' %}" 
        width="100%" 
        height="800px" 
        frameborder="0">
</iframe>

3. Convert .dot to SVG + Add Drag with Interact.js

If you prefer working with static SVGs but want to add drag functionality, you can convert your .dot file to an SVG first, then use the Interact.js library to make nodes draggable.

Step-by-Step:

  • Convert your .dot file to SVG using Graphviz’s dot command:
    dot -Tsvg path/to/your/models.dot -o static/graphs/models.svg
    
  • Download Interact.js and add it to your static/js folder.
  • In your Django template, embed the SVG and add the drag logic:
{% load static %}
<object id="model-svg" data="{% static 'graphs/models.svg' %}" type="image/svg+xml" style="width: 100%; height: 800px;"></object>

<script src="{% static 'js/interact.min.js' %}"></script>
<script>
  // Wait for the SVG to load
  document.getElementById('model-svg').addEventListener('load', function() {
    const svgDoc = this.contentDocument;
    // Target all node elements in the SVG
    const nodes = svgDoc.querySelectorAll('.node');
    
    nodes.forEach(node => {
      interact(node)
        .draggable({
          inertia: true,
          listeners: {
            move(event) {
              const target = event.target;
              // Get current position
              const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
              const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
              
              // Update position
              target.setAttribute('transform', `translate(${x}, ${y})`);
              target.setAttribute('data-x', x);
              target.setAttribute('data-y', y);
            }
          }
        });
    });
  });
</script>

All three methods will give you draggable model nodes—pick the one that fits your workflow best! If you run into snags with any of these, feel free to ask for more details.

内容的提问来源于stack exchange,提问作者Mark Koval

火山引擎 最新活动