2010-05-11 91 views
10

我使用名爲UserExtension的自定義用戶簡檔擴展了Django的用戶模型。 它通過唯一的ForeignKey關係與用戶相關,這使我可以在管理員中以聯機形式對其進行編輯! 我使用的信號爲每個新用戶創建一個新的配置文件:Django:在Django Admin中使用唯一外鍵的UserProfile

def create_user_profile(sender, instance, created, **kwargs): 
    if created: 
     try: 
      profile, created = UserExtension.objects.get_or_create(user=instance) 
     except: 
      pass 

post_save.connect(create_user_profile, sender=User) 

(這裏描述例如:Extending the User model with custom fields in Django) 的問題是,如果我通過管理創建一個新用戶,保存時出現IntegritiyError「列user_id不唯一」。它似乎不是信號被調用兩次,但我想管理員正試圖保存配置文件AFTERWARDS? 但我需要通過信號創建,如果我在系統的其他部分創建一個新用戶!

+0

我們可以看看你的get_or_create管理器嗎? – Brant 2010-05-11 18:11:22

+0

這是django的默認管理器! – 2010-05-11 22:13:28

回答

15

這是正常的Django會之後創建的管理實例,作爲保存總是由這樣的事:

  1. 創建用戶對象
  2. 創建配置文件對象(不能是之前因爲它指向給用戶)。

保存用戶對象時,django ORM無法知道創建配置文件對象會在它後面出現,所以它不會以任何方式延遲post_save信號(甚至沒有意義)。

,如果你想保持post_save信號來處理這個(恕我直言)的最好辦法,是重寫的UserExtension的保存方法是這樣的:

def save(self, *args, **kwargs): 
    try: 
     existing = UserExtension.objects.get(user=self.user) 
     self.id = existing.id #force update instead of insert 
    except UserExtension.DoesNotExist: 
     pass 
    models.Model.save(self, *args, **kwargs) 

要注意,這迫使每個插入該指向與現有對象相同的用戶成爲更新,這可能是其他代碼部分的意外行爲。

+0

覆蓋模型的默認保存方法對我來說似乎是個好主意,必須在所有用例中檢查它是否適用於我! 我認爲「現存= UserExtension.objects.all()。get(user = self.user)」可以是「existing = UserExtension.objects.get(user = self.user)」,或者你有什麼特別的想法接着就,隨即? :) 謝謝! – 2010-05-12 09:29:19

+0

沒什麼特別的,就我所知,你不需要'.all()'。我不知道爲什麼我加了它 – KillianDS 2010-05-12 16:32:18