Search code examples
djangodjango-modelsdjango-signals

Signals in Django


I have 2 models.py files in different app directories: users.models.py and friends.models.py.

There is one problem: if some user deleted from UserProfile model, all his friendship network must be deleted too with him. It is very natural.

But when I import Frienship to users.model.py I've got an error: Cannot import name Friendship

I understand an error arose because of mutual importing in these 2 files, and I know I can easely solve this problem with the help of signals, but I do not know how to do it in proper way.

Could anybody help in this particular case?

In users.models.py:

from friends.models import Friendship

class UserProfile(models.Model):
    username = models.Charfield(max_length=50)
    ...

    def delete(self, *args, **kwargs):
        Friendship.objects.remove_all(self)
        self.delete(*args, **kwargs)

In friends.models.py:

from users.models import UserProfile

class FriendshipManager(models.Manager):
    def remove_all(self, user):
        usr = Friendship.objects.get(user=user).friends
        frs = [i.user for i in usr.all()]
        for fr in frs:
            usr.remove(fr)

class Friendship(models.Model):
    user = models.Foreignkey(UserProfile)
    friends = models.ManyToManyField('self')

    objects = FriendshipManager()

Thanks in advance!!!


Solution

  • No need for signals, just use the magic *_set property. It will be defined at runtime so you don't have to worry about circular imports.

    friends/models.py

    from users.models import UserProfile
    
    class Friendship(models.Model):
        user = models.Foreignkey(UserProfile)
        friends = models.ManyToManyField('self')
    

    users/models.py

    class UserProfile(models.Model):
        username = models.Charfield(max_length=50)
        ...
    
        def delete(self, *args, **kwargs):
            for f in self.friendship_set.all():
                f.delete()
            super(self.__class__, self).delete(*args, **kwargs)