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\$

closed as off-topic by Mathias Ettinger, Ludisposed, Donald.McLean, alecxe, Graipher Feb 9 at 15:15

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Mathias Ettinger, Ludisposed, Donald.McLean, alecxe, Graipher
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\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\$ – Mathias Ettinger Feb 6 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 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\$ – Mathias Ettinger Feb 6 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 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.