diff --git a/pybb/signals.py b/pybb/signals.py index a650b7ab..114fe25c 100644 --- a/pybb/signals.py +++ b/pybb/signals.py @@ -21,9 +21,16 @@ def post_saved(instance, **kwargs): def post_deleted(instance, **kwargs): - profile = util.get_pybb_profile(instance.user) - profile.post_count = instance.user.posts.count() - profile.save() + Profile = util.get_pybb_profile_model() + User = compat.get_user_model() + try: + profile = util.get_pybb_profile(instance.user) + except (Profile.DoesNotExist, User.DoesNotExist) as e: + #When we cascade delete an user, profile and posts are also deleted + pass + else: + profile.post_count = instance.user.posts.count() + profile.save() def user_saved(instance, created, **kwargs): diff --git a/pybb/tests.py b/pybb/tests.py index cbd0cb4f..9dd969c5 100644 --- a/pybb/tests.py +++ b/pybb/tests.py @@ -31,7 +31,10 @@ raise Exception('PyBB requires lxml for self testing') from pybb import defaults -from pybb.models import Topic, TopicReadTracker, Forum, ForumReadTracker, Post, Category, PollAnswer, Profile +from pybb.models import Topic, TopicReadTracker, Forum, ForumReadTracker, Post, Category, PollAnswer + + +Profile = util.get_pybb_profile_model() __author__ = 'zeus' @@ -1854,3 +1857,18 @@ def test_profile_autocreation_middleware(self): self.assertIsNotNone(profile) self.assertEqual(type(profile), util.get_pybb_profile_model()) user.delete() + + def test_user_delete_cascade(self): + user = User.objects.create_user('cronos', 'cronos@localhost', 'cronos') + profile = getattr(user, defaults.PYBB_PROFILE_RELATED_NAME, None) + self.assertIsNotNone(profile) + post = Post(topic=self.topic, user=user, body='I \'ll be back') + post.save() + user_pk = user.pk + profile_pk = profile.pk + post_pk = post.pk + + user.delete() + self.assertFalse(User.objects.filter(pk=user_pk).exists()) + self.assertFalse(Profile.objects.filter(pk=profile_pk).exists()) + self.assertFalse(Post.objects.filter(pk=post_pk).exists()) diff --git a/runtests.py b/runtests.py index 44cec74a..287bc253 100644 --- a/runtests.py +++ b/runtests.py @@ -82,6 +82,7 @@ STATIC_URL='/static/', TEMPLATE_DIRS=(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test/test_project/templates'), ), PYBB_ATTACHMENT_ENABLE=True, + PYBB_PROFILE_RELATED_NAME='pybb_customprofile', MIDDLEWARE_CLASSES=MIDDLEWARE_CLASSES, TEMPLATE_CONTEXT_PROCESSORS=TEMPLATE_CONTEXT_PROCESSORS, AUTH_USER_MODEL='test_project.CustomUser', diff --git a/test/test_project/models.py b/test/test_project/models.py index 2350115f..f9ef14c2 100644 --- a/test/test_project/models.py +++ b/test/test_project/models.py @@ -1,8 +1,13 @@ from __future__ import unicode_literals + import django +from django.core.urlresolvers import reverse +from django.db import models + +from pybb.compat import get_user_model_path, get_username_field +from pybb.profiles import PybbProfile if django.VERSION[:2] >= (1, 5): - from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager from django.utils import timezone @@ -30,4 +35,21 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): objects = CustomUserManager() class Meta: - abstract = False \ No newline at end of file + abstract = False + + +class CustomProfile(PybbProfile): + user = models.OneToOneField(get_user_model_path(), + verbose_name='linked account', + related_name='pybb_customprofile', + blank=False, null=False,) + + class Meta(object): + verbose_name = 'Profile' + verbose_name_plural = 'Profiles' + + def get_absolute_url(self): + return reverse('pybb:user', kwargs={'username': getattr(self.user, get_username_field())}) + + def get_display_name(self): + return self.user.get_username()