如何在Django中建立经理与员工关联,实现数据隔离?
解决方案
1. 基础修正:创建员工时绑定当前经理
首先要确保经理创建员工账号时,自动将当前登录的经理(其User实例)关联到员工的manager字段,这是建立关联的核心前提。
函数视图实现示例
from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect from .models import Employee, User @login_required def create_employee(request): if request.method == 'POST': # 处理表单数据,创建员工的User账号 username = request.POST.get('username') email = request.POST.get('email') user = User.objects.create_user(username=username, email=email) # 将当前登录的经理绑定为该员工的直属上级 Employee.objects.create(user=user, manager=request.user) # 执行发送设置密码邮件的逻辑... return redirect('employee_list') return render(request, 'create_employee.html')
类视图(CreateView)实现示例
from django.views.generic.edit import CreateView from django.contrib.auth.mixins import LoginRequiredMixin from .models import Employee class EmployeeCreateView(LoginRequiredMixin, CreateView): model = Employee fields = ['user'] # 根据实际表单需求调整字段 def form_valid(self, form): # 手动为员工绑定当前登录的经理 form.instance.manager = self.request.user return super().form_valid(form)
2. 过滤员工列表:仅展示当前经理的下属
在员工列表视图中,通过过滤查询集,只保留与当前登录用户关联的员工:
函数视图实现示例
@login_required def employee_list(request): # 仅查询当前经理创建的员工 employees = Employee.objects.filter(manager=request.user) return render(request, 'employee_list.html', {'employees': employees})
类视图(ListView)实现示例
from django.views.generic.list import ListView from django.contrib.auth.mixins import LoginRequiredMixin from .models import Employee class EmployeeListView(LoginRequiredMixin, ListView): model = Employee template_name = 'employee_list.html' def get_queryset(self): # 重写查询集,仅返回当前经理的下属 return Employee.objects.filter(manager=self.request.user)
3. 模型逻辑优化(可选)
当前Employee的manager字段关联的是User模型,你可以改为关联Manager模型,这样能从数据库层面确保只有经理能成为员工的上级,逻辑更严谨:
修改后的Employee模型:
class Employee(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) # 关联到Manager模型而非User manager = models.ForeignKey(Manager, related_name='employees', on_delete=models.CASCADE) is_employee = models.BooleanField(default=True) def __str__(self): return self.user.username
对应的视图代码也要同步调整:
- 创建员工时:
# 函数视图中 manager_instance = Manager.objects.get(user=request.user) Employee.objects.create(user=user, manager=manager_instance) # 类视图中 def form_valid(self, form): form.instance.manager = Manager.objects.get(user=self.request.user) return super().form_valid(form)
- 查询员工列表时:
# 函数视图 employees = Employee.objects.filter(manager__user=request.user) # 类视图get_queryset方法 return Employee.objects.filter(manager__user=self.request.user)
4. 权限加固:防止越权操作
为避免经理通过URL直接访问不属于自己的员工页面,需要在详情、编辑、删除视图中添加权限校验:
函数视图权限校验示例
@login_required def edit_employee(request, pk): employee = Employee.objects.get(pk=pk) # 校验当前用户是否是该员工的直属经理 if employee.manager != request.user: # 返回权限拒绝页面或重定向到列表页 return redirect('employee_list') # 后续编辑逻辑...
类视图自定义权限Mixin示例
from django.core.exceptions import PermissionDenied class EmployeePermissionMixin: def get_object(self, queryset=None): obj = super().get_object(queryset) # 校验当前用户是否有权限操作该员工 if obj.manager != self.request.user: raise PermissionDenied return obj class EmployeeUpdateView(LoginRequiredMixin, EmployeePermissionMixin, UpdateView): model = Employee fields = ['...'] # 根据实际需求设置可编辑字段
内容的提问来源于stack exchange,提问作者Burdetiu Samuel
相关产品推荐
相关产品推荐

