0
\$\begingroup\$

I'm creating a Django project where users can decide to delete their account and everything we know about them (solved riddles, votes ...). I think you can compress this code but I don't know how.

I have a User related to Comment, Report, Vote, .... And I've got a Userprofile with a user relation:

class UserProfile(models.Model):
    User = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name="Benutzer", unique=True, primary_key=True, default=None)
    # Some other fields

Comment-User relation:

class Comment(models.Model):
    User = models.ForeignKey(User, on_delete=models.CASCADE, default=None, verbose_name="Kommentierender")

Report, Vote, UserClicked, UserVoted, SolvedRiddle have the same relation like Comment.

Article-User relation:

class Article(models.Model):
    authors = models.ManyToManyField(User, verbose_name="Autor", blank=True, default=None)

that's my del method in userprofile to delete everything from a user:

def __del__(self):
    user = self.User
    if user is None:
        return False
    Comment.objects.filter(User=user).delete()
    Report.objects.filter(User=user).delete()
    Vote.objects.filter(User=user).delete()

    userclicked = UserClicked.objects.filter(User=user)
    if userclicked.exists():
        for object in userclicked:
            del object

    uservoted = UserVoted.objects.filter(User=user)
    if uservoted.exists():
        for object in uservoted:
            del object

    author_article = Article.objects.filter(authors__in=[user, ])
    if author_article.exists():
        for object in author_article:
            object.remove_author(user)

    solvedriddle_user = SolvedSolution.objects.filter(User=user)
    if solvedriddle_user.exists():
        for object in solvedriddle_user:
            del object

    self.User.delete()
    self.delete()
    return True
\$\endgroup\$
  • \$\begingroup\$ Also did you test this code? I mean, did you manage to create Comments, Reports, etc. that are lasting in the DB between manual testing sessions? \$\endgroup\$ – 301_Moved_Permanently Feb 6 '19 at 16:35
  • \$\begingroup\$ It's a method of my userprofile model. I'll test it after I've compressed it. \$\endgroup\$ – Myzel394 Feb 6 '19 at 16:35
  • 1
    \$\begingroup\$ And if you didn't test the code, then it is not ready for review. How would you know if it work as expected? \$\endgroup\$ – 301_Moved_Permanently Feb 6 '19 at 16:45
  • \$\begingroup\$ I tested it. I had to change del object to obj.__del__(). After that it worked. Do you know how to compress this code? I think you can compress for object in * but I don't know how. \$\endgroup\$ – Myzel394 Feb 6 '19 at 17:01
1
\$\begingroup\$

This is not how deleting objects work in Django.

The __del__ method is a Python mechanism and is called when an object is garbage collected. This would be a huge mess if database rows were dropped anytime an object goes out of scope. This is also why calling del object doesn't seem to have any side effect: Django still caches the value somewhere, you just got rid of your variable.

Instead, you should use the delete() method on a model instance or on a queryset. But in fact none of this code is required as the on_delete=models.CASCADE will take care of that for you: as soon as a User object is deleted, the other linked objects will be deleted as well.

The only thing missing is to automatically delete the User instance when a UserProfile instance is deleted. This is better implemented using signals as it will be called for both usages discussed earlier.

Alternatively, you can provide a method on your UserProfile model that will delete the underlying User and, thus, everything related to it:

def delete_user(self):
    self.User.delete()

But you won't be able to use it for bulk deletions.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.