views:

107

answers:

2

I've been using django-mptt in my project for a while now, it's fabulous. Recently, I've found a need to override a model's save() method that uses mptt, and I'm getting an error when I try to save a new instance of that model:

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

I'm assuming that this is a result of the fact that the instance hasn't been stuck into a tree yet, but I'm not sure how to go about fixing this. I added a comment about it onto a similar issue on the project's tracker, but I was hoping that someone here might be able to put me on the right track faster.

Here's the traceback.

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
A: 

Solved this with a small addition to my custom save method. Had to change it from

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

to this:

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)
saturdayplace
A: 

changing the order should also work, since the object should get an id upon saving and the save()-method isn' returning anything!

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