我正在 Django 中使用自定义构建装饰器。
我的decorators.py:
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
def industry_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='app2:request_login'):
actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_Industry,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
这里的 is_Industry
是一个布尔值,来自models.py。
我的views.py:
@method_decorator(industry_required, name='dispatch')
class industryDetails(DetailView):
model = Industry
template_name = 'app/industryDetails.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['inserted_text'] = "inserted text from EmployeeDetails of views.py"
return context
在urls.py中:
path('industryDetails/<int:pk>/', views.industryDetails.as_view(), name='industryDetails')
models.py 如果需要,也包括在内:
class myCustomeUser(AbstractUser):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=20, unique="True", blank=False)
password = models.CharField(max_length=20, blank=False)
is_Employee = models.BooleanField(default=False)
is_Inspector = models.BooleanField(default=False)
is_Industry = models.BooleanField(default=False)
is_Admin = models.BooleanField(default=False)
class Industry(models.Model):
user = models.OneToOneField(myCustomeUser, on_delete=models.CASCADE, primary_key=True, related_name='industry_releted_user')
name = models.CharField(max_length=200, blank=True)
owner = models.CharField(max_length=200, blank=True)
license = models.IntegerField(null=True, unique=True)
industry_extrafield = models.TextField(blank=True)
现在我的问题是,假设拥有 primary_key=3
的用户可以通过使用 primary_key=2
(通过更改此地址路径中的主键)轻松访问具有 http://127.0.0.1:8000/industryDetails/2/
的另一个用户的数据.我需要为我的项目停止这个。我该如何编码,让任何用户都只能访问他自己的详细信息?
答案 0 :(得分:2)
这与装饰器本身无关,您只需要过滤以防止人们访问另一个 Industry
,因此:
@method_decorator(industry_required, name='dispatch')
class industryDetails(LoginRequiredMixin, DetailView):
model = Industry
template_name = 'app/industryDetails.html'
def get_queryset(self):
return Industry.objects.filter(user=self.request.user)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['inserted_text'] = "inserted text from EmployeeDetails of views.py"
return context
然而,由于每个用户最多可以拥有 一个 Industry
,因此您可能不应该向 URL 添加主键。因此,您可以定义如下路径:
path('industryDetails/', views.industryDetails.as_view(), name='industryDetails')
并在视图中覆盖 get_object
方法:
from django.shortcuts import get_object_or_404
@method_decorator(industry_required, name='dispatch')
class industryDetails(LoginRequiredMixin, DetailView):
model = Industry
template_name = 'app/industryDetails.html'
def get_object(self):
return get_object_or_404(Industry, user=self.request.user)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['inserted_text'] = "inserted text from EmployeeDetails of views.py"
return context