2011-10-28 52 views
2

我在不同的應用程序目錄中有2個models.py文件:users.models.py和friends.models.py。Django中的信號

存在一個問題:如果某位用戶從UserProfile模型中刪除,則他的所有友情網絡都必須同時刪除。這很自然。

但是,當我輸入之間的友誼,以users.model.py我得到了一個錯誤:無法導入名稱友誼

我明白這2個文件的出現是因爲相互進口的錯誤,我知道我可以在信號的幫助下輕鬆解決這個問題,但我不知道如何以適當的方式做到這一點。

有人可以幫助在這種特殊情況下?

在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

你正在尋找了錯誤的方式。循環進口是設計不好的標誌。現在是時候重構,而不是時間來尋找解決方法。與此密切相關的模型應該是同一個應用程序的一部分。 –

+0

我同意@Chris Pratt –

+0

但是會有超過600行的非常大的models.py文件。我想分開這些類... –

回答

1

無需信號來實現,只需用神奇的* _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) 
+0

和friendship_set是友誼類中的用戶字段的自動related_name或什麼? –

+1

這是正確的 –

+0

謝謝,尋求幫助。 –

1

這是我平時做,你可以很容易地重構這個與模型

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)