覆盖使用django-mptt的模型的save()方法

时间:2010-05-14 19:52:48

标签: django django-mptt

我已经在我的项目中使用django-mptt了一段时间,这太棒了。最近,我发现需要覆盖使用mptt的模型的save()方法,当我尝试保存该模型的新实例时,我收到错误:

Exception Type: ValueError at /admin/scrivener/page/add/
Exception Value: Cannot use None as a query value

我假设这是因为实例还没有插入树中,但我不确定如何解决这个问题。我在该项目的跟踪器上添加了关于它的类似问题的评论,但我希望这里的某个人能够更快地让我走上正确的轨道。

这是追溯。

Environment:

Request Method: POST
Request URL: http://localhost:8000/admin/scrivener/page/add/
Django Version: 1.2 rc 1 SVN-13117
Python Version: 2.6.4
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.admin',
 'django.contrib.sitemaps',
 'mptt',
 'filebrowser',
 'south',
 'haystack',
 'django_static',
 'etc',
 'scrivener',
 'gregor',
 'annunciator']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware')


Traceback:
File "B:\django-apps\3rd Party Source\django\core\handlers\base.py" in get_response
  100.                     response = callback(request, *callback_args, **callback_kwargs)
File "B:\django-apps\3rd Party Source\django\contrib\admin\options.py" in wrapper
  239.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "B:\django-apps\3rd Party Source\django\utils\decorators.py" in _wrapped_view
  74.                     response = view_func(request, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\views\decorators\cache.py" in _wrapped_view_func
  69.         response = view_func(request, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\contrib\admin\sites.py" in inner
  190.             return view(request, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\utils\decorators.py" in _wrapper
  21.             return decorator(bound_func)(*args, **kwargs)
File "B:\django-apps\3rd Party Source\django\utils\decorators.py" in _wrapped_view
  74.                     response = view_func(request, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\utils\decorators.py" in bound_func
  17.                 return func(self, *args2, **kwargs2)
File "B:\django-apps\3rd Party Source\django\db\transaction.py" in _commit_on_success
  299.                     res = func(*args, **kw)
File "B:\django-apps\3rd Party Source\django\contrib\admin\options.py" in add_view
  795.                 self.save_model(request, new_object, form, change=False)
File "B:\django-apps\3rd Party Source\django\contrib\admin\options.py" in save_model
  597.         obj.save()
File "B:\django-apps\scrivener\models.py" in save
  205.      self.url = self.get_absolute_url()
File "B:\django-apps\3rd Party Source\django\utils\functional.py" in _curried
  55.         return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
File "B:\django-apps\3rd Party Source\django\db\models\base.py" in get_absolute_url
  940.     return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\db\models\__init__.py" in inner
  31.         bits = func(*args, **kwargs)
File "B:\django-apps\scrivener\models.py" in get_absolute_url
  194.      for ancestor in self.get_ancestors():
File "B:\django-apps\3rd Party Source\mptt\models.py" in get_ancestors
  23.         opts.tree_id_attr: getattr(self, opts.tree_id_attr),
File "B:\django-apps\3rd Party Source\django\db\models\manager.py" in filter
  141.         return self.get_query_set().filter(*args, **kwargs)
File "B:\django-apps\3rd Party Source\django\db\models\query.py" in filter
  550.         return self._filter_or_exclude(False, *args, **kwargs)
File "B:\django-apps\3rd Party Source\django\db\models\query.py" in _filter_or_exclude
  568.             clone.query.add_q(Q(*args, **kwargs))
File "B:\django-apps\3rd Party Source\django\db\models\sql\query.py" in add_q
  1131.                             can_reuse=used_aliases)
File "B:\django-apps\3rd Party Source\django\db\models\sql\query.py" in add_filter
  1000.                 raise ValueError("Cannot use None as a query value")

Exception Type: ValueError at /admin/scrivener/page/add/
Exception Value: Cannot use None as a query value

2 个答案:

答案 0 :(得分:6)

通过我的自定义保存方法的一小部分解决了这个问题。不得不从

改变它
def save(self, *args, **kwargs):
    self.url = self.get_absolute_url()
    super(Page, self).save(*args, **kwargs)

到此:

def save(self, *args, **kwargs):
    if not self.id:
        Page.tree.insert_node(self, self.parent)
    self.url = self.get_absolute_url()
    super(Page, self).save(*args, **kwargs)

答案 1 :(得分:0)

更改顺序也应该有效,因为对象应该在保存时获得id并且save() - 方法不会返回任何内容!

def save(self, *args, **kwargs):
    super(Page, self).save(*args, **kwargs)    
    self.url = self.get_absolute_url()