Fixtures and multi-table inheritance

200 views
Skip to first unread message

Piotr Czachur

unread,
Dec 3, 2009, 8:16:54 AM12/3/09
to Django users
I got two models in myapp:
### myapp/models.py
class Animal(models.Model):
name = models.CharField()

class Cat(Animal):
tail_length = models.DecimalField()
###
This is Django multi-table inheritance, so both models have its tables
in database in one-to-one relation.
Is it possible to provide fixtures only inside Cat model:
### myapp/fixtures/initial_data.yaml
- model: myapp.Cat
pk: 1
fields:
name: kittie
tail_length: 33
###
and this fixtures will be propagated to both tables, or should I
create seaprate fixtures for Animal and Cat models?
It would be user friendly, and really fit one-to-one relationship.

PS.
Now when I try to load such mixed fixture, django makes insert into
myapp_cat table, before is has done insert to myapp.Animal, so
obviously foreign key constraint fails, so looks like it's not
supported.

Piotr Czachur

unread,
Dec 4, 2009, 3:41:22 AM12/4/09
to Django users
To be more specific I created sample application called "animal":
### mypro/animal/models.py
from django.db import models
class Animal(models.Model):
name = models.CharField(max_length=30, primary_key=True)
class Cat(Animal):
tail_length = models.DecimalField(max_digits=4, decimal_places=2)


### mypro/animal/fixtures/initial_data.yaml
- model: animal.Cat
pk: 1
fields:
name: Sonny
tail_length: 10


### bash
python manage.py syncdb
Creating table animal_animal
Creating table animal_cat
Installing yaml fixture 'initial_data' from '/tmp/mypro/../mypro/
animal/fixtures'.
Problem installing fixture '/tmp/mypro/../mypro/animal/fixtures/
initial_data.yaml': Traceback (most recent call last):
File "/usr/lib/pymodules/python2.6/django/core/management/commands/
loaddata.py", line 153, in handle
obj.save()
File "/usr/lib/pymodules/python2.6/django/core/serializers/base.py",
line 163, in save
models.Model.save_base(self.object, raw=True)
File "/usr/lib/pymodules/python2.6/django/db/models/base.py", line
495, in save_base
result = manager._insert(values, return_id=update_pk)
File "/usr/lib/pymodules/python2.6/django/db/models/manager.py",
line 177, in _insert
return insert_query(self.model, values, **kwargs)
File "/usr/lib/pymodules/python2.6/django/db/models/query.py", line
1087, in insert_query
return query.execute_sql(return_id)
File "/usr/lib/pymodules/python2.6/django/db/models/sql/
subqueries.py", line 320, in execute_sql
cursor = super(InsertQuery, self).execute_sql(None)
File "/usr/lib/pymodules/python2.6/django/db/models/sql/query.py",
line 2369, in execute_sql
cursor.execute(sql, params)
File "/usr/lib/pymodules/python2.6/django/db/backends/util.py", line
19, in execute
return self.cursor.execute(sql, params)
File "/usr/lib/pymodules/python2.6/django/db/backends/mysql/
base.py", line 84, in execute
return self.cursor.execute(query, args)
File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 166, in
execute
self.errorhandler(self, exc, value)
File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py", line 35,
in defaulterrorhandler
raise errorclass, errorvalue
IntegrityError: (1452, 'Cannot add or update a child row: a foreign
key constraint fails (temp file operation failed)')

And these are queries run in MySQL:
091204 9:40:13 771 Connect root@localhost on animal
771 Query SET storage_engine=INNODB
771 Query SET NAMES utf8
771 Query SET SESSION sql_mode='TRADITIONAL'
771 Query set autocommit=0
771 Query SHOW TABLES
771 Query commit
091204 9:40:14 771 Query commit
771 Query SELECT (1) AS `a` FROM `animal_cat` WHERE
`animal_cat`.`animal_ptr_id` = 1
771 Query INSERT INTO `animal_cat` (`animal_ptr_id`,
`tail_length`) VALUES (1, '10.00')
771 Query rollback

It fails because, it inserts first to child table, and there is of
course integrity errer from MySQL.


### And why such fixture does not work, while specifying model data in
following way works:
python manage.py shell
In [1]: from animal import models
In [1]: from animal import models
In [2]: c = models.Cat()
In [3]: c.name = 'Sonny'
In [4]: c.tail_length = 10
In [5]: c.save()
In [6]:
##

If django figured out how to insert data for model created via
manage.py shell, it should easily does the same when loading fixtures
but now it just fails.
Am I doing something wrong, or such fixtures loading is not supported?
Reply all
Reply to author
Forward
0 new messages