Reputation: 71
What I got:
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(unique=True)
full_slug = models.CharField(max_length=256, null=True, blank=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
class Work(models.Model):
title = models.CharField(max_length=128, unique=True)
slug = models.SlugField(max_length=128, unique=True)
category = TreeManyToManyField(Category, verbose_name='parent category', related_name='works')
url = models.CharField(max_length=256, null=True, blank=True)
def save(self, *args, **kwargs):
if self.category:
self.url = '%s/%s' % (self.category.full_slug, self.slug)
else:
self.url = '%s' % self.slug
super(Work, self).save(*args, **kwargs)
But I get an error "'ManyRelatedManager' object has no attribute 'full_slug'". Actually I need only one category, so I tried self.url = '%s/%s' % (self.category.all()[0].full_slug, self.slug)
, but I get the error anyway.
So, is there a way to solve this? The only way I get it working is with category=TreeForeignKey
, but I need a TreeManyToManyField
Traceback:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/website/work/1/change/
Django Version: 1.9.5
Python Version: 3.5.1
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mptt',
'django_mptt_admin',
'website']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "E:\web\env\lib\site-packages\django\core\handlers\base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "E:\web\env\lib\site-packages\django\core\handlers\base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "E:\web\env\lib\site-packages\django\contrib\admin\options.py" in wrapper
541. return self.admin_site.admin_view(view)(*args, **kwargs)
File "E:\web\env\lib\site-packages\django\utils\decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "E:\web\env\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "E:\web\env\lib\site-packages\django\contrib\admin\sites.py" in inner
244. return view(request, *args, **kwargs)
File "E:\web\env\lib\site-packages\django\contrib\admin\options.py" in change_view
1440. return self.changeform_view(request, object_id, form_url, extra_context)
File "E:\web\env\lib\site-packages\django\utils\decorators.py" in _wrapper
67. return bound_func(*args, **kwargs)
File "E:\web\env\lib\site-packages\django\utils\decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "E:\web\env\lib\site-packages\django\utils\decorators.py" in bound_func
63. return func.__get__(self, type(self))(*args2, **kwargs2)
File "C:\Python35\Lib\contextlib.py" in inner
30. return func(*args, **kwds)
File "E:\web\env\lib\site-packages\django\contrib\admin\options.py" in changeform_view
1378. self.save_model(request, new_object, form, not add)
File "E:\web\env\lib\site-packages\django\contrib\admin\options.py" in save_model
991. obj.save()
File "E:\web\website\models.py" in save
63. self.url = '%s/%s' % (self.category.full_slug, self.slug)
Exception Type: AttributeError at /admin/website/work/1/change/
Exception Value: 'ManyRelatedManager' object has no attribute 'full_slug'
Upvotes: 0
Views: 1280
Reputation: 12265
In simple terms you are getting this error because if you look at your code
category = TreeManyToManyField(Category, verbose_name='parent category', related_name='works')
Its a many-to-many-field So here:
def save(self, *args, **kwargs):
if self.category:
self.url = '%s/%s' % (self.category.full_slug, self.slug)
you are saying give me category.full_slug
And django is politely telling you that there can be multiple categories for and Work instance.
So its up to you to figure out which self.category instance you want.
e.g.
self.category.first().full_slug
Read more here: https://docs.djangoproject.com/en/1.9/ref/models/relations/
Of course self.category.first() may not exist if you don't have any Category instances that are related to the Work instance you are trying to save.
On a highly related note, you need to save the Work instance first before associating any m2m models to your Work instance.
Upvotes: 0