【发布时间】:2009-12-14 11:27:50
【问题描述】:
如果我有一个处理朋友管理的视图,这意味着有一个视图来处理添加、删除、阻止、取消阻止以及接受/拒绝成为朋友的邀请。我遇到的问题是,当我尝试向用户提供有意义的错误时,这些错误最终会出现在他们不应该出现的 url 上。
例如,如果 User1 和 User2 已经是朋友,并且 User1 转到将 User2 添加为的 url一个朋友而不是表单,就像他们不是朋友一样呈现,并且表单在 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]))
如果没有这样的用户,这还包括检查和有意义的错误消息(而不是 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
如果视图在外壳中被绕过并且表单被独立使用,则会进一步复制为表单验证错误。
我要问的是,是否有一种更 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 模式的文件中定义,装饰器将包装视图函数以运行所有测试,如果有任何失败则重定向,如果一切正常,最后将其传递给视图函数。这会是一种有效的管理方法,不会用数百行样板代码阻塞视图文件吗?
编辑2:
我也有兴趣了解其他人如何做类似的事情。我怀疑我是第一个想要向用户显示消息而不是仅仅抛出 404 页面的人。
【问题讨论】:
标签: django validation error-handling views