views:

121

answers:

3

I'm using django-mptt to manage a simple CMS, with a model called Page, which looks like this (most presumably irrelevant fields removed):

class Page(mptt.Model, BaseModel):
  title    = models.CharField(max_length = 20)
  slug     = AutoSlugField(populate_from = 'title')
  contents = models.TextField()
  parent   = models.ForeignKey('self', null=True, blank=True, 
         related_name='children', help_text = u'The page this page lives under.')

removed fields are called attachments, headline_image, nav_override, and published

All works fine using SQLite, but when I use MySQL and try and add a Page using the admin (or using ModelForms and the save() method), I get this:

ProgrammingError at /admin/mycms/page/add/
(1110, "Column 'level' specified twice")

where the SQL generated is:

'INSERT INTO `kaleo_page` (`title`, `slug`, `contents`, `nav_override`, `parent_id`,  
`published`, `headline_image_id`, `lft`, `rght`, `tree_id`, `level`, `lft`, `rght`,    
`tree_id`, `level`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'

for some reason I'm getting the django-mptt fields (lft, rght, tree_id and level) twice. It works in SQLite presumably because SQLite is more forgiving about what it accepts than MySQL.

get_all_field_names() also shows them twice:

>>> Page._meta.get_all_field_names()
['attachments', 'children', 'contents', 'headline_image', 'id', 'level', 'lft',
'nav_override', 'parent', 'published', 'rght', 'slug', 'title', 'tree_id']

Which is presumably why the SQL is bad. What could I have done that would result in those fields appearing twice in get_all_field_names()?

+1  A: 

I noticed that you're inheriting from multiple base classes, class Page(mptt.Model, BaseModel):. Are the fields that are being duplicated found on both of those models?

T. Stone
Argh - sorry, should have removed that. No. I've tested without the multiple inheritance and get the same behaviour. That was my first guess too.
Dominic Rodger
+1  A: 

Since you are using a branch of mptt that allows for inheritance, lets assume that inheriting mptt.Model is the same as using mptt.register().

# Page and TrunkPage are basically the same
class Page(branched_mptt.Models, BaseModel):
    # ...

class TrunkPage(BaseModel):
    # ...
trunk_mptt.register(TrunkPage, order_insertion_by=['title'])

Do you see duplicate fields when you run manage.py sqlall? It looks OK using the branched_mptt when I run it with sqlite3 or mysql:

$ ./manage.py sqlall kaleo
BEGIN;
CREATE TABLE `kaleo_page` (
    [ ... ]
    `lft` integer UNSIGNED NOT NULL,
    `rght` integer UNSIGNED NOT NULL,
    `tree_id` integer UNSIGNED NOT NULL,
    `level` integer UNSIGNED NOT NULL
)
[ ... ]

If that output looks OK, what about your PageAdmin? Are you doing anything fancy there? If so, have you tried with a plain vanilla model admin for Page?

# admin.py
from django.contrib import admin
from kaleo.models import Page

admin.site.register(Page)
istruble
Sorry - another instance of my question not being clear - I'm using Ben Firshman's fork of django-mptt (http://github.com/bfirsh/django-mptt), which uses inheritance instead of registering
Dominic Rodger
Thanks for your help (and +1 for the effort!) Output of `sqlall` only shows the fields once, and I still get the error even if I just use `admin.site.register(Page)`. Any other ideas?
Dominic Rodger
Not much else comes to mind atm. The only other thing I would do is try it on a fresh DB and then start adding pieces one at a time until the problem is triggered. Not a fun or easy next step but it should help you track down the source of the problem. Also try your kaleo app in a fresh project with it as the only app -- anything to eliminate other variables helps.
istruble
+1  A: 

The problem appeared to be that the fields were being dynamically added twice (I think because of the way settings.py is imported twice.

I ended up fixing it by using the regular version of django-mptt, and adding this to my __init__.py:

from cbc.kaleo.models import Page
import mptt

try:
    mptt.register(Page)
except mptt.AlreadyRegistered:
    pass

Not the prettiest thing in the world, but it works!

Dominic Rodger