2009-12-14 16 views
1

如果我有一個處理朋友管理的視圖,這意味着可以處理添加,刪除,阻止,解除封鎖以及接受/拒絕成爲好友的邀請。我碰到的問題是,當我嘗試向最終在他們不應該在的url的用戶提供有意義的錯誤時。很好地重定向錯誤,沒有太多的複製/粘貼?

例如,如果用戶1 用戶2 已經和朋友用戶1轉到URL添加用戶2作爲一個朋友,而不是形式呈現的,好像他們是不是朋友和形式失敗在unique_together = (('user_from', 'user_to'),)上顯示警告消息,並在顯示錶單之前將它們重定向到適當的頁面。

喜歡這張

def add_friend(request, username): 
    try: 
     user = User.objects.get(username=username) 
    except User.DoesNotExist: 
     messages.error(request, 'A user with the username %s does not exist. \ 
      Try searching for the user below.' % username) 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

    if Friend.objects.are_friends(request.user, user): 
     messages.error(request, 'You are already friends with %s' % user) 
     return HttpResponseRedirect(reverse('profiles_profile_detail', args=[user])) 

這也包括一個校驗和meaningfull錯誤消息(而不是404),如果不存在這樣的用戶。

,很容易處理,但與其他檢查它長到

def add_friend(request, username): 
    try: 
     user = User.objects.get(username=username) 
    except User.DoesNotExist: 
     messages.error(request, 'A user with the username %s does not exist. \ 
      Try searching for the user below.' % username) 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

    if user == request.user: 
     messages.error(request, 'You are already friends with yourself') 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

    if Enemy.objects.is_blocked(request.user, user): 
     messages.error(request, '%s has blocked you from adding them as a friend' % user) 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

    if Enemy.objects.has_blocked(request.user, user): 
     messages.error(request, 'You have blocked %s so you cannot add them as a friend' % user) 
     return HttpResponseRedirect(reverse('profiles_profile_detail', args=[user])) 

    if Friend.objects.are_friends(request.user, user): 
     messages.error(request, 'You are already friends with %s' % user) 
     return HttpResponseRedirect(reverse('profiles_profile_detail', args=[user])) 

    if FriendRequest.objects.invitation_sent(request.user, user): 
     messages.error(request, 'You already sent %s a request. You need to \ 
      wait for them to reply to it.' % user) 
     return HttpResponseRedirect(reverse('friends_pending')) 

    if FriendRequest.objects.invitation_received(request.user, user): 
     messages.error(request, '%s already sent you a request and is waiting \ 
      for you to respond to them.' % user) 
     return HttpResponseRedirect(reverse('friends_pending')) 

所有這一切都在

  • REMOVE_FRIEND
  • block_user
  • unblock_user
  • pending_invitations
  • 再次複製

如果在shell中忽略視圖並且獨立使用表單,則會進一步複製爲表單驗證錯誤。

我在問的是,如果在沒有過度複製和粘貼的情況下有更多的pythonic方法來完成此操作?

編輯

我一直在試圖解決這個問題,並在想,如果這樣的事情會是一個很好的方式。

tests = ((Enemy.objects.is_blocked, 'This user has blocked you', reverse('friends_find_friend')), 
     (Enemy.objects.has_blocked, 'You have blocked this user', reverse('profiles_profile_detail', args=[user])),) 

for test in tests: 
    if test[0](request.user, user): 
     messages.error(request, test[1]) 
     return HttpResponseRedirect(test[2]) 

的測試將在類似的URL模式和一個裝飾會換到了所有的測試運行視圖功能的其它文件中定義,重定向如果出現任何故障,並最終將其傳遞給視圖功能,如果一切好。這會成爲一種有效的方法來管理,而不會用數百行樣板代碼堵塞視圖文件?

EDIT2

我也希望看到別人怎麼做類似的事情。我懷疑我是第一個想要向用戶顯示消息的人,而不是僅僅投擲404頁面。

回答

0

我想象的代碼並不完全是內部remove_friendblock_user等複製(因爲消息會有所不同) - 你也許可以重構你的一些功能融入其中,需要兩個用戶,並返回某種狀態表示成功的獨立輔助功能或失敗。

如果沒有樣品說你的pending_invitations視圖(這可能與add_friend最相似),很難更有幫助。

+0

的'它提交按鈕pending_invitations'只是檢查按下(確認或否認),其作用很像另一個兩個視圖使用相同的檢查來調用'accept'或'deny',以確保用戶存在,有待處理的請求,您不試圖接受您發送的請求等。 – Rigsby 2009-12-14 18:59:32

1

Python裝飾器是完美的。

定義你在裝飾器中所做的所有驗證,並用這個裝飾你所有的add_friendremove_friend等。

更新:

對於您的情況下,它會是這個樣子:

def do_friending_validation(fun): 
    def validate_function(*args,**kwargs): 
     try: 
      user = User.objects.get(username=username) 
     except User.DoesNotExist: 
      messages.error(request, 'A user with the username %s does not exist. \ 
       Try searching for the user below.' % username) 
      return HttpResponseRedirect(reverse('friends_find_friend')) 

     if user == request.user: 
     messages.error(request, 'You are already friends with yourself') 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

     if Enemy.objects.is_blocked(request.user, user): 
     messages.error(request, '%s has blocked you from adding them as a friend' % user) 
     return HttpResponseRedirect(reverse('friends_find_friend')) 

     if Enemy.objects.has_blocked(request.user, user): 
     messages.error(request, 'You have blocked %s so you cannot add them as a friend' % user) 
     return HttpResponseRedirect(reverse('profiles_profile_detail', args=[user])) 

     if Friend.objects.are_friends(request.user, user): 
     messages.error(request, 'You are already friends with %s' % user) 
     return HttpResponseRedirect(reverse('profiles_profile_detail', args=[user])) 

     if FriendRequest.objects.invitation_sent(request.user, user): 
     messages.error(request, 'You already sent %s a request. You need to \ 
      wait for them to reply to it.' % user) 
     return HttpResponseRedirect(reverse('friends_pending')) 

     if FriendRequest.objects.invitation_received(request.user, user): 
     messages.error(request, '%s already sent you a request and is waiting \ 
      for you to respond to them.' % user) 
     return HttpResponseRedirect(reverse('friends_pending')) 
     fun(*args,**kwargs) 

    return validate_function 

@do_friending_validation 
def add_friend(request, username): 

    #Do your stuff here 

@do_friending_validation  
def remove_friend(request, username): 

    #Do your stuff here 
+0

我想過使用裝飾器,但唯一的驗證保持完全一樣是第一個用戶。其他人的消息將會非常輕微(即,你已經是'add_friends'的朋友,並且你還不是'remove_friends'中的朋友。 – Rigsby 2009-12-14 18:13:15

+0

然後只需在裝飾器中設置錯誤標誌並選擇基於裝飾器中標誌裝飾器的消息視圖。 – kibitzer 2009-12-15 07:42:59