3 ms·
Show HN: Easily Visualize Your SQLAlchemy Data Models in a Nice SVG Diagram
I made this on Friday for fun, but I think it could be useful for people. If your application has pretty complicated SQLalchemy data models (and the app I'm working on now has gotten super complicated, with dozens of models with complex interconnections), then this very easily generates an attractive SVG that you can open in the browser showing all your tables and how they are connected. You can be up and running with this in less than a minute— just open it in Google Colab, replace the sample data models with your own, and run the notebook, and you should see the SVG displayed almost immediately at the bottom.
I attempted to also generate an HTML file containing the embedded SVG as well as some JS to enable nice interactive hover-on effects (I wanted to highlight the border of the table you hover over and then change all the outgoing connections to other tables to be red, and all incoming connections to that table to be green), but it wasn't working and started turning into a slog after an hour. If anyone knows how to do this, please submit a PR!
- eigenvalue 3y agoIn case anyone knows why it doesn't work, here is the function I wrote to enable more interactive effects using HTML: def generate_html_with_embedded_svg(svg_filename, html_filename): with open(svg_filename, 'r') as f: svg_content = f.read() # Add an ID to the SVG tag svg_content = re.sub(r'<svg ', '<svg id="embedded-svg" ', svg_content, 1) html_content = '''<!DOCTYPE html> <html> <head> <title>Interactive SVG</title> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", function() { let svgElement = document.getElementById('embedded-svg'); let tables = svgElement.querySelectorAll('.table-hover'); tables.forEach(function(table) { table.addEventListener('mouseover', function() { let tableId = table.getAttribute('id'); table.setAttribute('stroke', 'blue'); table.setAttribute('stroke-width', '2'); let edgesTo = svgElement.querySelectorAll('.edge-to-hover-' + tableId); edgesTo.forEach(function(edge) { edge.setAttribute('stroke', 'red'); edge.setAttribute('stroke-width', '2'); }); let edgesFrom = svgElement.querySelectorAll('.edge-from-hover-' + tableId); edgesFrom.forEach(function(edge) { edge.setAttribute('stroke', 'green'); edge.setAttribute('stroke-width', '2'); }); }); table.addEventListener('mouseout', function() { let tableId = table.getAttribute('id'); table.removeAttribute('stroke'); table.removeAttribute('stroke-width'); let edgesTo = svgElement.querySelectorAll('.edge-to-hover-' + tableId); edgesTo.forEach(function(edge) { edge.removeAttribute('stroke'); edge.removeAttribute('stroke-width'); }); let edgesFrom = svgElement.querySelectorAll('.edge-from-hover-' + tableId); edgesFrom.forEach(function(edge) { edge.removeAttribute('stroke'); edge.removeAttribute('stroke-width'); }); }); }); }); </script> </head> <body> <div id="svg-container">''' + svg_content + '''</div> </body> </html>''' with open(html_filename, 'w') as f: f.write(html_content)
- breed101 3y agoThis is great! What a complicated graph tho.