Сигналы в Джанго - PullRequest
       16

Сигналы в Джанго

2 голосов
/ 28 октября 2011

У меня есть 2 файла models.py в разных каталогах приложений: users.models.py и friends.models.py.

Существует одна проблема: если какой-либо пользователь удален из модели UserProfile, вся его дружеская сеть также должна быть удалена вместе с ним. Это очень естественно.

Но когда я импортирую Frienship в users.model.py, у меня появляется ошибка: Невозможно импортировать имя Friendship

Я понимаю, что ошибка возникла из-за взаимного импорта в эти 2 файла, и я знаю, что могу легко решить эту проблему с помощью сигналов, но я не знаю, как это сделать правильно.

Может ли кто-нибудь помочь в этом конкретном случае?

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)

В 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()

Заранее спасибо !!!

Ответы [ 2 ]

1 голос
/ 28 октября 2011

Нет необходимости в сигналах, просто используйте магическое свойство * _set. Он будет определен во время выполнения, поэтому вам не нужно беспокоиться о циклическом импорте.

Друзья / models.py

from users.models import UserProfile

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

Пользователи / 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)
1 голос
/ 28 октября 2011

Это то, что я обычно делаю, вы можете легко реорганизовать это для реализации с вашей моделью

from django.db import models
from django.db.models.signals import post_save, post_delete
from django.contrib.auth.models import User

# App specific


class UserProfile(models.Model):
    """
    Adds a basic UserProfile for each User on the fly.
    """
    user = models.OneToOneField(User)
    avatar = models.ImageField(upload_to='example/somewhere', blank=True)

    def __str__(self):
          return "%s's profile" % self.user

    def get_avatar(self):
        return '/'+self.avatar

    def clean_avatar(self):
        # TODO: imagekit
        pass

    class Meta:
        app_label = 'users'

    def save(self, *args, **kwargs):
        if self.id:
            this = UserProfile.objects.get(id=self.id)
            if this.avatar:
                if this.avatar != self.avatar:
                    this.avatar.delete(save=False)
        super(UserProfile, self).save()

def create_user_profile(sender, instance, created, **kwargs):
    if created:
       profile, created = UserProfile.objects.get_or_create(user=instance)

post_save.connect(create_user_profile, sender=User)


def UserProfileDelete(instance, **kwargs):
    """
    Documentatie
    """
    instance.avatar.delete(save=False)

post_delete.connect(UserProfileDelete, sender=UserProfile)
...