django-mptt 字段出现两次,破坏了 SQL

发布于 2024-08-31 07:32:04 字数 1615 浏览 3 评论 0原文

我正在使用 django-mptt 来管理一个简单的 CMS,其模型名为 Page,如下所示(大多数可能是不相关的字段被删除):

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.')

删除的字段称为 attachments< /code>、headline_imagenav_overridepublished

使用 SQLite 都可以正常工作,但是当我使用 MySQL 并尝试添加时使用 admin 的页面(或使用 ModelForms 和 save() 方法),我得到这个:

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

生成的 SQL 是:

'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)'

出于某种原因,我得到了 django-mptt 字段(lftrghttree_idlevel)两次。它在 SQLite 中工作大概是因为 SQLite 比 MySQL 更宽容它所接受的内容。

get_all_field_names() 也显示它们两次:

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

这可能就是 SQL 不好的原因。我该怎么做才会导致这些字段在 get_all_field_names() 中出现两次?

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()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尾戒 2024-09-07 07:32:04

我注意到您继承了多个基类,class Page(mptt.Model, BaseModel):。在这两个模型上都找到了重复的字段吗?

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?

愿得七秒忆 2024-09-07 07:32:04

由于您使用的是允许继承的 mptt 分支,我们假设继承 mptt.Model与使用 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'])

运行 manage.py sqlall 时是否看到重复字段?当我使用sqlite3或mysql运行它时,使用branched_mptt看起来不错:

$ ./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
)
[ ... ]

如果该输出看起来不错,那么您的PageAdmin呢?你在那里做了什么奇特的事情吗?如果是这样,您是否尝试过使用普通的页面管理员模型?

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

admin.site.register(Page)

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)
淡笑忘祈一世凡恋 2024-09-07 07:32:04

问题似乎是这些字段被动态添加了两次(我认为是因为 settings.py 被导入了两次。

我最终通过使用常规方法修复了它django-mptt 版本,并将其添加到我的 __init__.py 中:

from cbc.kaleo.models import Page
import mptt

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

不是世界上最漂亮的东西,但它有效!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文