Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Easily Visualize Your SQLAlchemy Data Models in a Nice SVG Diagram (github.com/dicklesworthstone)
3 points by eigenvalue on Oct 30, 2023 | hide | past | favorite | 2 comments
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!




In 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)


This is great! What a complicated graph tho.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: