django-mptt fields showing up twice, breaking SQL
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/a开发者_C百科dd/
(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()
?
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?
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)
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!
精彩评论