根据现有模型限制用户查看
Restrict User from view based on existing model
我的 views.py
中有一些非常简单的观点。
class IndexView(generic.ListView):
template_name = 'voting/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Poll.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Poll.objects.filter(pub_date__lte=timezone.now())
class ResultsView(generic.DetailView):
model = Poll
template_name = 'voting/results.html'
context_object_name = 'question'
我还创建了一个 model
存储哪些用户被邀请参加哪些投票以及其他一些数据。
class EligibleVoters(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
poll = models.ForeignKey(Poll, on_delete=models.CASCADE, null=True)
encrypted_keypart = models.BinaryField(max_length=200, blank=True)
decrypted_keypart = models.BinaryField(max_length=200, blank=True)
class Meta:
unique_together = ["user", "poll"]
我想限制未受邀参加投票的用户查看任何这些投票。
我认为我想为每个视图做的是这样的事情,但我不确定这是否是正确的方法。
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
if EligibleVoters.objects.filter(poll=Poll.objects.id, user=self.request.user.id).exists():
return Poll.objects.filter(pub_date__lte=timezone.now())
else:
return render('voting/somethingsomething.html')
})
我应该以这种方式限制对特定民意调查的访问吗?此外,上面的代码并没有真正起作用并给出了一些错误,但我不确定我是否应该继续并尝试以这种方式修复它。
您应该从 Poll 到 User 添加一个多对多字段,使用 EligibleVoter 作为直通字段:
eligible_users = models.ManyToManyField('User', through='EligibleVoter')
现在您可以:
return Poll.objects.filter(eligible_users=self.request.user, pub_date__lte=timezone.now())
过滤 eligblevoters
上的查询集
get_queryset
不渲染输出,它只产生一个查询集。
不过,我们可以通过添加额外的过滤来使用它来限制访问:
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
return super(DetailView, self).get_queryset().filter
<b>eligiblevoters__user=self.request.user</b>,
pub_date__lte=timezone.now()
)
在其他视图中应使用类似的方法。
这是如何工作的
查询工作如下。通过定义从 EligibleVoters
到 User
的 ForeignKey
(命名为 user
),然后 Django 反向创建一个 implicit 关系:你可以例如使用 User.eligblevoters_set
查询以获得相关的 EligableVoters
查询集。我们还可以使用 elgiblevoters
.
对其进行过滤
因此我们添加了两个额外的过滤条件:pub_date__lte=timezone.now()
用于过滤之前发布的帖子(现在包括在内),以及 eligiblevoters__user=self.request.user
。这意味着我们添加了一个约束,即 至少 相关 eligablevoters
之一应该具有 user
self.request.user
(此特定会话的用户).
所以如果没有这样的Post
,那么我们就无法得到Poll
和请求的id
。
渲染以防找不到对象
我们还可以在找不到对象的情况下呈现页面,例如通过使用 try
-except
和 Http404
修补 .get(..)
函数,然后呈现特定页面,例如:
<b>from django.http import Http404</b>
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
return super(DetailView, self).get_queryset().filter
eligiblevoters__user=self.request.user,
pub_date__lte=timezone.now()
)
def get(request, *args, **kwargs):
try:
return super(DetailView, self).get(request, *args, **kwargs)
<b>except Http404:
return render(request, 'app/template_not_found.html', {})</b>
所以这里我们渲染一个(可能是不同的模板),这里有一个空的上下文,当然你可以让它更高级。
我的 views.py
中有一些非常简单的观点。
class IndexView(generic.ListView):
template_name = 'voting/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Poll.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Poll.objects.filter(pub_date__lte=timezone.now())
class ResultsView(generic.DetailView):
model = Poll
template_name = 'voting/results.html'
context_object_name = 'question'
我还创建了一个 model
存储哪些用户被邀请参加哪些投票以及其他一些数据。
class EligibleVoters(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
poll = models.ForeignKey(Poll, on_delete=models.CASCADE, null=True)
encrypted_keypart = models.BinaryField(max_length=200, blank=True)
decrypted_keypart = models.BinaryField(max_length=200, blank=True)
class Meta:
unique_together = ["user", "poll"]
我想限制未受邀参加投票的用户查看任何这些投票。
我认为我想为每个视图做的是这样的事情,但我不确定这是否是正确的方法。
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
if EligibleVoters.objects.filter(poll=Poll.objects.id, user=self.request.user.id).exists():
return Poll.objects.filter(pub_date__lte=timezone.now())
else:
return render('voting/somethingsomething.html')
})
我应该以这种方式限制对特定民意调查的访问吗?此外,上面的代码并没有真正起作用并给出了一些错误,但我不确定我是否应该继续并尝试以这种方式修复它。
您应该从 Poll 到 User 添加一个多对多字段,使用 EligibleVoter 作为直通字段:
eligible_users = models.ManyToManyField('User', through='EligibleVoter')
现在您可以:
return Poll.objects.filter(eligible_users=self.request.user, pub_date__lte=timezone.now())
过滤 eligblevoters
上的查询集
get_queryset
不渲染输出,它只产生一个查询集。
不过,我们可以通过添加额外的过滤来使用它来限制访问:
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
return super(DetailView, self).get_queryset().filter
<b>eligiblevoters__user=self.request.user</b>,
pub_date__lte=timezone.now()
)
在其他视图中应使用类似的方法。
这是如何工作的
查询工作如下。通过定义从 EligibleVoters
到 User
的 ForeignKey
(命名为 user
),然后 Django 反向创建一个 implicit 关系:你可以例如使用 User.eligblevoters_set
查询以获得相关的 EligableVoters
查询集。我们还可以使用 elgiblevoters
.
因此我们添加了两个额外的过滤条件:pub_date__lte=timezone.now()
用于过滤之前发布的帖子(现在包括在内),以及 eligiblevoters__user=self.request.user
。这意味着我们添加了一个约束,即 至少 相关 eligablevoters
之一应该具有 user
self.request.user
(此特定会话的用户).
所以如果没有这样的Post
,那么我们就无法得到Poll
和请求的id
。
渲染以防找不到对象
我们还可以在找不到对象的情况下呈现页面,例如通过使用 try
-except
和 Http404
修补 .get(..)
函数,然后呈现特定页面,例如:
<b>from django.http import Http404</b>
class DetailView(generic.DetailView):
model = Poll
template_name = 'voting/detail.html'
context_object_name = 'question'
def get_queryset(self):
return super(DetailView, self).get_queryset().filter
eligiblevoters__user=self.request.user,
pub_date__lte=timezone.now()
)
def get(request, *args, **kwargs):
try:
return super(DetailView, self).get(request, *args, **kwargs)
<b>except Http404:
return render(request, 'app/template_not_found.html', {})</b>
所以这里我们渲染一个(可能是不同的模板),这里有一个空的上下文,当然你可以让它更高级。