Django:如何为用户/组设置Model实例的限时查看权限
解决Django中带过期时间的Item实例访问权限控制问题
嘿,作为Django新手碰到这种自定义权限的需求完全正常,官方默认的权限系统确实没法直接覆盖“按实例+时间过期”的场景,咱们一步步来实现这个功能:
1. 先设计权限关联模型
首先需要一个中间模型,用来记录每个用户对每个Item的访问权限及过期时间。在你的models.py里添加:
from django.db import models from django.contrib.auth.models import User from django.utils import timezone class Item(models.Model): # 这里是你原有的Item模型字段,比如: name = models.CharField(max_length=100) content = models.TextField() class ItemAccessPermission(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="item_permissions") item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name="access_permissions") expiration_time = models.DateTimeField() created_at = models.DateTimeField(auto_now_add=True) class Meta: # 确保一个用户对同一个Item只有一条权限记录 unique_together = ('user', 'item') def is_valid(self): # 判断权限是否有效(未过期) return self.expiration_time > timezone.now()
2. 重写DetailView的权限验证逻辑
接下来修改你的DetailView,在获取Item实例前先检查当前用户是否拥有有效的访问权限。如果没有权限或者权限已过期,直接抛出权限拒绝的异常:
from django.views.generic.detail import DetailView from django.core.exceptions import PermissionDenied from .models import Item, ItemAccessPermission from django.utils import timezone class ItemDetailView(DetailView): model = Item template_name = 'item_detail.html' # 替换成你的模板路径 def get_object(self, queryset=None): # 先获取要展示的Item实例 obj = super().get_object(queryset=queryset) # 检查当前用户是否有有效的访问权限 try: permission = ItemAccessPermission.objects.get(user=self.request.user, item=obj) if not permission.is_valid(): raise PermissionDenied("您对该Item的访问权限已过期") except ItemAccessPermission.DoesNotExist: raise PermissionDenied("您没有访问该Item的权限") return obj
3. 权限的授予与管理
现在你需要有给用户分配权限的方式,比如:
- 在Django后台管理中注册
ItemAccessPermission模型,手动添加权限记录 - 写一个视图来批量/手动分配权限,比如:
from django.shortcuts import get_object_or_404, redirect from .models import Item, ItemAccessPermission from django.utils import timezone from datetime import timedelta def grant_item_access(request, item_id): # 示例:给当前用户分配该Item的7天访问权限 item = get_object_or_404(Item, id=item_id) # 先检查是否已有权限,有就更新过期时间,没有就创建 permission, created = ItemAccessPermission.objects.get_or_create( user=request.user, item=item, defaults={'expiration_time': timezone.now() + timedelta(days=7)} ) if not created: permission.expiration_time = timezone.now() + timedelta(days=7) permission.save() return redirect('item_detail', pk=item_id)
4. 前端提示优化(可选)
如果想在模板里更友好地提示用户权限状态,可以在视图里把权限信息传递到模板:
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) permission = ItemAccessPermission.objects.get(user=self.request.user, item=self.object) context['permission_expiration'] = permission.expiration_time return context
然后在模板里显示:
<p>该Item访问权限将于:{{ permission_expiration|date:"Y-m-d H:i" }} 过期</p>
这样就能实现你要的“每个用户对指定Item的访问权限在指定时间后过期,过期无法查看”的需求啦~
内容的提问来源于stack exchange,提问作者hlcarriere
相关产品推荐
相关产品推荐

