Skip to content

Commit fbd0924

Browse files
committed
Implement a post_syncdb listener which checks database schema consistency
Since south cannot do non-linear and optional migrations (which would be necessary to activate and deactivate page extensions) we try at least to be a little more helpful than simply crashing upon non-existing columns. The user is informed upon syncdb that several columns might be missing. Please note that this has not been tested yet with ManyToManyFields -- they obviously do not show up when inspecting the primary table, and the code does not currently handle this.
1 parent 836f6e4 commit fbd0924

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

feincms/management/checker.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.core.management.color import color_style
2+
from django.db import connection
3+
4+
5+
def check_database_schema(cls, module_name):
6+
"""
7+
Returns a function which inspects the database table of the passed class.
8+
It checks whether all fields in the model are available on the database
9+
too. This is especially helpful for models with an extension mechanism,
10+
where the extension might be activated after syncdb has been run for the
11+
first time.
12+
13+
Please note that you have to connect the return value using strong
14+
references. Here's an example how to do this:
15+
16+
signals.post_syncdb.connect(check_database_schema(Page, __name__),
17+
weak=False)
18+
"""
19+
20+
def _fn(sender, **kwargs):
21+
if sender.__name__ != module_name:
22+
return
23+
24+
cursor = connection.cursor()
25+
26+
existing_columns = [row[0] for row in \
27+
connection.introspection.get_table_description(cursor, cls._meta.db_table)]
28+
29+
missing_columns = []
30+
31+
for field in cls._meta.fields:
32+
if field.column not in existing_columns:
33+
missing_columns.append(field)
34+
35+
if not missing_columns:
36+
return
37+
38+
style = color_style()
39+
40+
print style.ERROR('The following columns seem to be missing in the database table %s:' % cls._meta.db_table)
41+
for field in missing_columns:
42+
print u'%s:%s%s' % (
43+
style.SQL_KEYWORD(field.column),
44+
' ' * (25 - len(field.column)),
45+
u'%s.%s' % (field.__class__.__module__, field.__class__.__name__),
46+
)
47+
48+
print style.NOTICE('\nPlease consult the output of `python manage.py sql %s` to find out what the correct column types are.\n' % (
49+
cls._meta.app_label,
50+
))
51+
return _fn

feincms/module/blog/models.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
from django.conf import settings
44
from django.contrib import admin
55
from django.db import models
6-
from django.db.models import Q
6+
from django.db.models import Q, signals
77
from django.http import Http404
88
from django.utils.translation import ugettext_lazy as _
99

1010
from feincms.admin import editor
11+
from feincms.management.checker import check_database_schema
1112
from feincms.models import Base
1213
from feincms.utils import get_object
1314

@@ -61,6 +62,8 @@ def register_extensions(cls, *extensions):
6162
fn(cls, EntryAdmin)
6263
cls._feincms_extensions.add(ext)
6364

65+
signals.post_syncdb.connect(check_database_schema(Entry, __name__), weak=False)
66+
6467

6568
class EntryAdmin(editor.ItemEditor, admin.ModelAdmin):
6669
date_hierarchy = 'published_on'

feincms/module/page/models.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.contrib import admin
77
from django.conf import settings
88
from django.db import models
9-
from django.db.models import Q
9+
from django.db.models import Q, signals
1010
from django.http import Http404, HttpResponseRedirect
1111
from django.utils.translation import ugettext_lazy as _
1212
from django.core.urlresolvers import reverse
@@ -15,6 +15,7 @@
1515

1616
from feincms.admin import editor
1717
from feincms.admin.editor import django_boolean_icon
18+
from feincms.management.checker import check_database_schema
1819
from feincms.models import Region, Template, Base, ContentProxy
1920
from feincms.utils import get_object
2021

@@ -250,6 +251,7 @@ def register_extensions(cls, *extensions):
250251
Page.frontendediting_request_processor,
251252
Page.redirect_request_processor)
252253

254+
signals.post_syncdb.connect(check_database_schema(Page, __name__), weak=False)
253255

254256

255257
class PageAdmin(editor.ItemEditor, editor.TreeEditor):

0 commit comments

Comments
 (0)