Opened 6 years ago

Closed 6 years ago

#13974 closed (wontfix)

saving object with multi-table inheritance is not transactional by default

Reported by: Chris Curvey Owned by: nobody
Component: Database layer (models, ORM) Version: 1.2
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


if you are using multi-table inheritance, and there is some problem writing to one of the tables, some tables are updated, and some are not.

(MySQL 5.x on Ubuntu, Django 1.2rc 1 on Windows)

1) Set up a new project with database settings like so:

    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'mydb',
        'USER': 'myuser',
        'PASSWORD': 'mypassword'
        'HOST': 'myhost',
        'PORT': '', 
        'OPTIONS' : {
            'init_command' : 'set storage_engine=INNODB',


2) Now set up some models that use inheritance:

from django.db import models

# Create your models here.

class Foo(models.Model):
    a = models.IntegerField()
class Bar(Foo):
    b = models.IntegerField()

3) Now create a script that does something obviously wrong.

import sys

import os
os.environ["DJANGO_SETTINGS_MODULE"] = 'settings'

from foobar.models import Bar

# try testing something that is clearly wrong.
bar = Bar(a=1, b="A")

# this is going to throw a ValueError

4) Now go look at the underlying tables in MySQL:

mysql> select * from foobar_foo;
| id | a |
|  1 | 1 |
1 row in set (0.00 sec)

mysql> select * from foobar_bar;
Empty set (0.00 sec)

The workaround is to add @commit_on_success and a save() method to Bar, like so, but it seems (to me) like this should be unncessary.

from django.db.transaction import commit_on_success

class Bar(Foo):
    b = models.IntegerField()
    def save(self):
        super(Bar, self).save()

Change History (1)

comment:1 Changed 6 years ago by Johannes Dollinger

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Resolution: wontfix
Status: newclosed

Django cannot know the scope of your transaction. At best, could be wrapped with a savepoint.

Note: See TracTickets for help on using tickets.
Back to Top