限制对Django通用视图的访问

时间:2014-10-10 15:08:33

标签: python django django-generic-views

我正在创建一个Django应用,用户可以为其创建帐户,然后为每个帐户添加交易。它的一部分网站将允许用户跟踪投资收益。我正在利用泛型类视图来实现这一目标。

用户将交易添加到特定帐户(代码未显示),然后他们必须能够使用site / transactions / 2 /查看该特定帐户的交易,其中2是帐户ID。

问题是任何已登录的用户都可以更改网址以获取其他用户帐户的交易。我可以通过检查给定的帐户ID属于用户来轻松解决此问题,但我认为必须有更好的方法。我有更好的方法来实现这一目标吗?我可能不会对此进行URL编码吗?我并不喜欢用户在数据库中查看帐户ID的想法。

此外,在稍后阶段,我希望用户可以查看他们的一些帐户'单个列表中的事务。例如,显示其5个帐户中的3个帐户的所有交易。然后这个URL方法也不会真正起作用。我还有其他选择吗?

在models.py中我有:

class Account(models.Model):
    name = models.CharField(max_length=40, unique=True, db_index=True)
    user = models.ForeignKey(User)

class Transaction(models.Model):
    value = models.DecimalField(max_digits=15, decimal_places=2)
    date = models.DateField('transaction date')
    account = models.ForeignKey(Account)

在urls.py中:

url(r'^(?P<account_id>\d+)/$', views.IndexView.as_view(), name='index'),  

在views.py中:

class IndexView(LoginRequiredMixin, generic.ListView):
    model = Transaction

    def get_queryset(self):
        account_id = self.kwargs['account_id']
        queryset = Transaction.objects.filter(account_id=account_id)
        return queryset

然后我有transaction_list模板

由于

1 个答案:

答案 0 :(得分:1)

如果您想要出现404错误,可以使用辅助函数get_object_or_404()来首先获取帐户对象。

像这样:

def get_queryset(self):
    account_id = self.kwargs['account_id']

    # raise 404 if no account is found for the current user
    account = get_object_or_404(Account, pk=account_id, user=self.request.user)

    queryset = Transaction.objects.filter(account=account)
    return queryset

对于您提到的第二件事,您可以创建新视图,也可以只检查网址中是否有'account_id',然后重复使用当前视图。无论哪种方式,您都需要一个新网址。

urls.py:

url(r'^(?P<account_id>\d+)/$', views.IndexView.as_view(), name='index'),
url(r'^$', views.IndexView.as_view(), name='index'), 

如果网址中没有帐号ID,请再次修改get_queryset()

def get_queryset(self):
    # account_id will be None if the second url was the one that matched.
    account_id = self.kwargs.get('account_id', None) 

    if account_id:
        # raise 404 if no account is found for the current user
        account = get_object_or_404(Account, pk=account_id, user=self.request.user)

        queryset = Transaction.objects.filter(account=account)
    else:
        # we're going to show all transactions for the user, rather than a specific account
        queryset = Transaction.objects.filter(account__user=self.request.user)

    return queryset