fusionbox/django-fusionbox — Issue #13: fusionbox.behaviors breaks multi-table inheritance?
Author: chroto
Created: 2012-01-09 18:19:28+00:00
State: open

Writing a parent model that inherits from one or more behaviors causes children to throw an error on validate / syncdb / schemamigration

models.py:

~~~

from django.db import models

from fusionbox.behaviors import Timestampable, Publishable, SEO

class DescribableItem(models.Model):
title = models.CharField("Title", max_length=255)
short_description = models.TextField("Short Description", max_length=255)
long_description = models.TextField("Long Description", max_length=1000)

class Meta:
abstract = True

class Video(DescribableItem, Timestampable, Publishable):
video_link = models.URLField("Vimeo Link", max_length=255,
verify_exists=False)
featured = models.BooleanField("Is Featured?", default=False,
help_text="Checking this will place the video on the home page \
carousel")
image = models.ImageField(upload_to="images/videos",null=True,
help_text="Recommended dimensions: 630x360")

category = models.ManyToManyField("category.Category",
related_name='categories',
help_text = "Add a category to this video.")

class Meta:
ordering = ("created_at",)
verbose_name = "Video"
verbose_name_plural = "Videos"

def __unicode__(self):
return u"%s" % self.title

class BehindTheScenesVideo(Video):
pass
~~~

Stacktrace:

~~~

(zerosun)proto /var/sites/django/zerosun.com (master *)
$ python -m pdb ./manage.py validate
> /var/sites/django/zerosun.com/manage.py(2)()
-> import os, sys
(Pdb) c
Traceback (most recent call last):
File "/usr/lib/python2.6/pdb.py", line 1285, in main
pdb._runscript(mainpyfile)
File "/usr/lib/python2.6/pdb.py", line 1204, in _runscript
self.run(statement)
File "/usr/lib/python2.6/bdb.py", line 368, in run
exec cmd in globals, locals
File "", line 1, in
File "./manage.py", line 9, in
execute_from_command_line(sys.argv)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/__init__.py", line 422, in execute_from_command_line
utility.execute()
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/__init__.py", line 361, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/base.py", line 191, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/base.py", line 220, in execute
output = self.handle(*args, **options)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/base.py", line 351, in handle
return self.handle_noargs(**options)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/commands/validate.py", line 9, in handle_noargs
self.validate(display_num_errors=True)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/base.py", line 249, in validate
num_errors = get_validation_errors(s, app)
File "/home/chris/.virtualenvs/zerosun/src/django/django/core/management/validation.py", line 30, in get_validation_errors
for (app_name, error) in get_app_errors().items():
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/loading.py", line 158, in get_app_errors
self._populate()
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/loading.py", line 64, in _populate
self.load_app(app_name, True)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/loading.py", line 88, in load_app
models = import_module('.models', app_name)
File "/home/chris/.virtualenvs/zerosun/src/django/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "./portfolio/models.py", line 36, in
class BehindTheScenesVideo(Video):
File "/home/chris/.virtualenvs/zerosun/src/django-fusionbox/fusionbox/behaviors.py", line 48, in __new__
new_class = super(MetaBehavior, cls).__new__(cls, name, bases, attrs)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/base.py", line 161, in __new__
new_class.add_to_class(attr_name, field)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/base.py", line 220, in add_to_class
value.contribute_to_class(cls, name)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 978, in contribute_to_class
super(ForeignKey, self).contribute_to_class(cls, name)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 111, in contribute_to_class
add_lazy_relation(cls, self, other, resolve_related_class)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 73, in add_lazy_relation
operation(field, model, cls)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 110, in resolve_related_class
field.do_related_class(model, cls)
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 122, in do_related_class
self.set_attributes_from_rel()
File "/home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py", line 119, in set_attributes_from_rel
self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name
AttributeError: 'NoneType' object has no attribute 'name'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /home/chris/.virtualenvs/zerosun/src/django/django/db/models/fields/related.py(119)set_attributes_from_rel()
-> self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name
(Pdb) print self.rel.field_name
None
(Pdb) print self

(Pdb) print self.rel

(Pdb) print self.rel.to

(Pdb) print self.rel.to._meta
portfolio.video
(Pdb) print self.rel.to._meta.pk
None

~~~

For now, I have to inherit the behavior classes on the child class:

~~~
class BehindTheScenesVideo(Video, Publishable, Timestampable):
pass
~~~

or have both Video and BehindTheScenes video as separate tables inheriting from an abstract class