Login

PostgreSQL ON DELETE CASCADE

Author:
mjt
Posted:
November 13, 2009
Language:
Python
Version:
1.1
Tags:
database postgres foreign-key postgresql databases
Score:
1 (after 1 ratings)

Have you always been annoyed by how you set up this elaborate big database schema and weren't able to have ON DELETE CASCADE ON UPDATE CASCADE in dbshell?

This solves the problem; create the two files and and empty init.py and put them somewhere in your path.

Then say DATABASE_ENGINE='postgresql_psycopg2_cascade' in settings.

Really I'd like this to be in the ForeignKey object, were it upstream Django or an own version of it, but it doesn't seem possible.

Ideas on how to make this configurable are more than welcome!

Props go out to Ari Flinkman for the inspiration to do this!

 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
87
88
89
90
91
### postgresql_psycopg2_cascade/creation.py

# vim: tabstop=4 expandtab autoindent shiftwidth=4 fileencoding=utf-8

from django.db.backends.postgresql_psycopg2.base import DatabaseCreation as ODatabaseCreation # Overload me

## ON DELETE CASCADE ON UPDATE CASCADE

class DatabaseCreation(ODatabaseCreation):
    def sql_for_inline_foreign_key_references(self, field, known_models, style):
        res = ODatabaseCreation.sql_for_inline_foreign_key_references(self, field, known_models, style)

        # If not pending
        if not res[1]:
            for i in xrange(len(res[0])):
                res[0][i] = res[0][i].replace('DEFERRABLE', 'ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE')

        return res

    def sql_for_pending_references(self, model, style, pending_references):
        res = ODatabaseCreation.sql_for_pending_references(self, model, style, pending_references)

        for i in xrange(len(res)):
            res[i] = res[i].replace('DEFERRABLE', 'ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE')

        return res

    def sql_for_many_to_many_field(self, model, f, style):
        res = ODatabaseCreation.sql_for_many_to_many_field(self, model, f, style)

        for i in xrange(len(res)):
            res[i] = res[i].replace('DEFERRABLE', 'ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE')

        return res


# EOF

### postgresql_psycopg2_cascade/base.py

# vim: tabstop=4 expandtab autoindent shiftwidth=4 fileencoding=utf-8

from django.db.backends import BaseDatabaseValidation

from django.utils.safestring import SafeUnicode, SafeString

## Stuff required for postgresql_psycopg2 imported

from django.db.backends.postgresql_psycopg2.base import PostgresqlDatabaseOperations
from django.db.backends.postgresql_psycopg2.base import DatabaseClient
from django.db.backends.postgresql_psycopg2.base import get_version

from django.db.backends.postgresql_psycopg2.base import DatabaseFeatures
from django.db.backends.postgresql_psycopg2.base import DatabaseOperations
from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper as ODatabaseWrapper # Overload me

from django.db.backends.postgresql_psycopg2.base import DatabaseIntrospection

## Our stuff

from postgresql_psycopg2_cascade.creation import DatabaseCreation

class DatabaseWrapper(ODatabaseWrapper):
    def __init__(self, *args, **kwargs):
        super(DatabaseWrapper, self).__init__(*args, **kwargs)

        self.features = DatabaseFeatures()
        self.ops = DatabaseOperations()
        self.client = DatabaseClient()
        self.creation = DatabaseCreation(self)
        self.introspection = DatabaseIntrospection(self)
        self.validation = BaseDatabaseValidation()


## The essential copypasta

try:
    import psycopg2 as Database
    import psycopg2.extensions
except ImportError, e:
    from django.core.exceptions import ImproperlyConfigured
    raise ImproperlyConfigured("Error loading psycopg2 module: %s" % e)

DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)

# EOF

More like this

  1. Database Cache Management View by kedare 6 years, 3 months ago
  2. Override QuerySet.delete() (one way of preventing cascading deletes) by timbroder 5 years, 2 months ago
  3. Clear nullable foreign keys on delete by psagers 6 years, 3 months ago
  4. Custom model field for Frame or Box by binishkaspar 4 years, 1 month ago
  5. Database cleanup by skyjur 4 years, 8 months ago

Comments

guettli (on February 23, 2012):

Unfortunately I can't edit my last comment. I mean, you can modify the ON DELETE behavior in current django version.

#

Please login first before commenting.