0

Need help with one to one reverse lookup. My models:

class User(MarkedAsDeletedMixin):
    fields here

class UserProfile(MarkedAsDeletedMixin):
    user = models.OneToOneField(User)

class MarkedAsDeletedMixin(models.Model):
    marked_as_deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.marked_as_deleted = True
        self.save()

You can see I'm overriding the delete method so when I do someuser.userprofile.delete() I just mark the userprofile object as deleted.

The problem comes when I do someuser.userprofile after. I get userprofile, because I didn't delete the userprofile, I just marked it as deleted.

In order to get only userprofile objects not marked as deleted, I need to override User's one to one reverse lookup or do something with UserProfile's manager. Any ideas?

Adilet Maratov
  • 1,312
  • 2
  • 14
  • 24

2 Answers2

0

Technically, the record exists so overwriting user.profile to hide it would make no sense. That would make the code harder to understand.

You could add a method instead:

class User(MarkedAsDeletedMixin):
    def get_profile():
        return self.profile if self.profile and not self.profile.marked_as_deleted else None

class UserProfile(MarkedAsDeletedMixin):
    user = models.OneToOneField(User, related_name="profile")

This is a one to one relationship and the main entity is the User instance, not the UserProfile instance. In other words, the user is what's been used in most of the code. For example, in a view, you use request.user.

I'm not sure what a soft-deleted profile implies in your application but let's imagine it means it's not public. In that case I would save this in the User:

class User(MarkedAsDeletedMixin):
     is_profile_public = models.BooleanField(default=True)
François Constant
  • 5,531
  • 1
  • 33
  • 39
0

Yes, you could use a manager, you'd just have to modify get_queryset. It's probably best to put this on a Manager for the MarkedAsDeletedMixin—which should get inherited by any subclass. Something like this:

from django.db import models

class MarkedAsDeletedManager(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        return self.filter(marked_as_deleted=False)

class MarkedAsDeletedMixin(models.Model):
    marked_as_deleted = models.BooleanField(default=False)
    objects = MarkedAsDeletedManager()

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.marked_as_deleted = True
        self.save()
csinchok
  • 741
  • 3
  • 10