This page looks best with JavaScript enabled

Django Model and E-R Diagram

 ·  ☕ 6 min read

As requirements are gradually confirmed, the system’s DB model is gradually confirmed as well. Sometimes you use a tool like MySQL Workbench to draw an E-R diagram and then generate MySQL database tables, and at that point you need to reverse-generate Django Models; other times you write the Django Models directly, but then you need to look at the E-R diagram. This article mainly addresses the two needs above, implementing conversion between Django Models and E-R diagrams.

1. Generating the Model Relationship Diagram

Django provides the third-party package django-extensions, which can be used to generate an E-R diagram from the Models in Django.

1.1 Installing the Package

1
pip install django-extensions

1.2 Configuration

In the Django settings.py file, add django_extensions to INSTALLED_APPS.

1
2
3
INSTALLED_APPS = (
    'django_extensions',
)

1.3 Generating the dot File and the png Image

  • Generate the E-R diagram for all models
1
python manage.py graph_models -a > all.dot
  • Generate the dot file for a single Django App (using django_view_permission as an example).
1
python manage.py graph_models django_view_permission > django_view_permission.dot

The exported dot content is as follows:
django_view_permission.dot

digraph model_graph {
  // Dotfile by Django-Extensions graph_models
  // Created: 2018-03-03 14:55
  // Cli Options: django_view_permission

  fontname = "Helvetica"
  fontsize = 8
  splines  = true

  node [
    fontname = "Helvetica"
    fontsize = 8
    shape = "plaintext"
  ]

  edge [
    fontname = "Helvetica"
    fontsize = 8
  ]

  // Labels

  django_view_permission_models_CommonElement [label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    CommonElement
    </FONT></TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">create_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">DateTimeField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">doc</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">TextField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">update_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">DateTimeField</FONT>
    </TD></TR>

    </TABLE>
    >]

  django_view_permission_models_View [label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    View<BR/>&lt;<FONT FACE="Helvetica Italic">CommonElement</FONT>&gt;
    </FONT></TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT FACE="Helvetica Bold">id</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT FACE="Helvetica Bold">AutoField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">create_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">doc</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">TextField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">func</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">CharField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">module</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">CharField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">name</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica ">CharField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">update_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    </TABLE>
    >]

  django_view_permission_models_ViewSet [label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    ViewSet<BR/>&lt;<FONT FACE="Helvetica Italic">CommonElement</FONT>&gt;
    </FONT></TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT FACE="Helvetica Bold">id</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT FACE="Helvetica Bold">AutoField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">create_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">doc</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">TextField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT FACE="Helvetica ">name</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT FACE="Helvetica ">CharField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">update_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    </TABLE>
    >]

  django_view_permission_models_ViewPermission [label=<
    <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
    <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
    <FONT FACE="Helvetica Bold" COLOR="white">
    ViewPermission<BR/>&lt;<FONT FACE="Helvetica Italic">CommonElement</FONT>&gt;
    </FONT></TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT FACE="Helvetica Bold">id</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT FACE="Helvetica Bold">AutoField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">create_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">doc</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">TextField</FONT>
    </TD></TR>

    <TR><TD ALIGN="LEFT" BORDER="0">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">update_time</FONT>
    </TD><TD ALIGN="LEFT">
    <FONT COLOR="#7B7B7B" FACE="Helvetica Italic">DateTimeField</FONT>
    </TD></TR>

    </TABLE>
    >]
  // Relations

  django_view_permission_models_View -> django_view_permission_models_CommonElement
  [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both];

  django_view_permission_models_ViewSet -> django_view_permission_models_View
  [label="views (viewset)"] [arrowhead=dot arrowtail=dot, dir=both];

  django_view_permission_models_ViewSet -> django_view_permission_models_CommonElement
  [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both];
  account_models_BkUser [label=<
  <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0">
  <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4">
  <FONT FACE="Helvetica Bold" COLOR="white">BkUser</FONT>
  </TD></TR>
  </TABLE>
  >]
  django_view_permission_models_ViewPermission -> account_models_BkUser
  [label="users (viewpermission)"] [arrowhead=dot arrowtail=dot, dir=both];

  django_view_permission_models_ViewPermission -> django_view_permission_models_View
  [label="views (viewpermission)"] [arrowhead=dot arrowtail=dot, dir=both];

  django_view_permission_models_ViewPermission -> django_view_permission_models_ViewSet
  [label="views_set (viewpermission)"] [arrowhead=dot arrowtail=dot, dir=both];

  django_view_permission_models_ViewPermission -> django_view_permission_models_CommonElement
  [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both];
}
  • Generate the image

Since what is generated is a dot-format image description file, you need a tool to convert it into the commonly used PNG format. You can download graphviz and add /bin/dot.exe to the system PATH.

1
dot -Tpng django_view_permission.dot > django_view_permission.png

You can also use the online Dot preview tool GraphvizOnline to view it and download the PNG image.

2. Generating the Database’s models.py

Django has a built-in inspectdb command, which can use the database’s corresponding table relationships and fields to generate Django Models.

1
python manage.py inspectdb export_models.py

The exported file content is as follows:
export_models.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
#
# Also note: You'll have to insert the output of 'django-admin sqlcustom [app_label]'
# into your database.
from __future__ import unicode_literals

from django.db import models

class DjangoViewPermissionView(models.Model):
    doc = models.TextField(blank=True, null=True)
    create_time = models.DateTimeField()
    update_time = models.DateTimeField()
    module = models.CharField(max_length=255, blank=True, null=True)
    func = models.CharField(max_length=255, blank=True, null=True)
    name = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'django_view_permission_view'
        unique_together = (('func', 'module', 'name'),)


class DjangoViewPermissionViewPermission(models.Model):
    doc = models.TextField(blank=True, null=True)
    create_time = models.DateTimeField()
    update_time = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_permission'


class DjangoViewPermissionViewPermissionUsers(models.Model):
    viewpermission = models.ForeignKey(DjangoViewPermissionViewPermission)
    bkuser = models.ForeignKey(AuthUser)

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_permission_users'
        unique_together = (('viewpermission_id', 'bkuser_id'),)


class DjangoViewPermissionViewPermissionViews(models.Model):
    viewpermission = models.ForeignKey(DjangoViewPermissionViewPermission)
    view = models.ForeignKey(DjangoViewPermissionView)

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_permission_views'
        unique_together = (('viewpermission_id', 'view_id'),)


class DjangoViewPermissionViewPermissionViewsSet(models.Model):
    viewpermission = models.ForeignKey(DjangoViewPermissionViewPermission)
    viewset = models.ForeignKey('DjangoViewPermissionViewSet')

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_permission_views_set'
        unique_together = (('viewpermission_id', 'viewset_id'),)


class DjangoViewPermissionViewSet(models.Model):
    doc = models.TextField(blank=True, null=True)
    create_time = models.DateTimeField()
    update_time = models.DateTimeField()
    name = models.CharField(unique=True, max_length=255)

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_set'


class DjangoViewPermissionViewSetViews(models.Model):
    viewset = models.ForeignKey(DjangoViewPermissionViewSet)
    view = models.ForeignKey(DjangoViewPermissionView)

    class Meta:
        managed = False
        db_table = 'django_view_permission_view_set_views'
        unique_together = (('viewset_id', 'view_id'),)

Note that when using the migrate command to create database tables, Models with managed = False will be ignored.

3. References


微信公众号
WRITTEN BY
微信公众号