2011-10-28 4 views
2

users.models.pyとfriends.models.pyの2つのmodels.pyファイルがあります。Djangoのシグナル

1つの問題があります:ユーザーがUserProfileモデルから削除した場合、彼の友情ネットワークもすべて削除する必要があります。それはとても自然です。

しかし、ときに私は、私はエラーを持っているusers.model.pyするFrienshipをインポート:は、名前の友情

をインポートすることはできません私はエラーがこれらの2つのファイルであるため、相互インポートの生じた、と私は理解してシグナルの助けを借りて、この問題を簡単に解決できることは知っていますが、私は正しい方法でそれをどうやってやるのか分かりません。

この特定のケースで誰かを助けることができますか? users.models.pyで

:friends.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) 

:事前に

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

あなたは間違った方法、それを見ています。循環輸入は、悪い設計の兆候です。回避策を見つける時間ではなく、リファクタリングの時間です。密接に関係するこのモデルは、同じアプリの一部である必要があります。 –

+0

私は@Chris Prattに同意します –

+0

しかし、600行以上の非常に大きなmodels.pyファイルがあります。私はこれらのクラスを分離したいと思っていた... –

答えて

1

信号を必要とすることなく実現するために、これをリファクタリングできます。実行時に定義されるので、循環インポートについて心配する必要はありません。

友人/ 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) 
+0

、friendship_setはFriendshipクラスのユーザーフィールドの自動related_nameですか? –

+1

これは正しいです –

+0

ありがとうございました。 –

1

これは私が通常何をすべきかは、あなただけで簡単に魔法* _setプロパティを使用し、お使いのモデル

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) 
関連する問題