如何限制用户仅能访问指定动态URL页面并仅更新自身员工记录?
解决用户仅能更新自身员工记录的问题
要实现这个权限控制,核心是把登录用户和对应的Employee记录绑定起来,然后在更新视图中验证这种关联关系。下面分步骤给出具体的解决方案:
第一步:给Employee模型添加User关联(推荐方案)
目前你的User和Employee是通过用户名规则间接关联的,这种方式不够可靠且不易维护。最规范的做法是给Employee添加一个一对一外键字段,直接关联到Django的User模型:
修改models.py中的Employee类:
from django.contrib.auth.models import User class Employee(models.Model): emp_id = models.AutoField(primary_key=True) emp_first_name = models.CharField(max_length=50) emp_last_name = models.CharField(max_length=50, default='') email = models.EmailField() salary = models.IntegerField() joining_date = models.DateField() department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True) designation = models.ForeignKey(Designation, on_delete=models.SET_NULL, null=True) country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True) state = models.ForeignKey(State, on_delete=models.SET_NULL, null=True) city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True) sys_gen_pass = models.CharField(max_length=50, blank=True) # 添加一对一外键关联User user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True) # 修正原有的__str__方法(原代码中emp_name不存在) def __str__(self): return f"{self.emp_first_name} {self.emp_last_name}"
修改完成后,运行数据库迁移命令:
python manage.py makemigrations python manage.py migrate
第二步:修改new视图,关联User到Employee记录
在创建User账号后,把这个User对象绑定到对应的Employee记录上:
修改views.py中的new函数:
def new(request): if request.method == 'GET': form = EmployeeForm return render(request, 'new.html', {'form': form}) else: form = EmployeeForm(request.POST) if form.is_valid(): # 生成密码逻辑保持不变 string = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_=+-[]{};:,./<>?" password_length = 12 password = "".join(random.sample(string, password_length)) form.save() latest=Employee.objects.last() latest.sys_gen_pass = password # 创建User逻辑保持不变 def remove(string): return string.replace(" ", "") e_name = remove(latest.emp_first_name) + remove(latest.emp_last_name) + str(latest.emp_id) e_email = latest.email user_password = latest.sys_gen_pass user = User.objects.create_user(e_name, e_email, user_password) user.first_name = latest.emp_first_name user.last_name = latest.emp_last_name user.save() # 新增:把User绑定到Employee记录 latest.user = user latest.save() return redirect('home')
第三步:在update视图中添加权限验证
现在在更新视图里,检查当前登录用户是否是该员工记录对应的User,如果不匹配则拒绝访问:
修改views.py中的update函数:
from django.http import HttpResponseForbidden from django.contrib import messages @login_required(login_url='loginuser') def update(request, id): try: emp_record = Employee.objects.get(pk=id) except Employee.DoesNotExist: messages.error(request, "该员工记录不存在!") return redirect('home') # 核心权限验证:只有当前用户是该员工对应的User才能更新 if emp_record.user != request.user: messages.error(request, "你没有权限修改这条记录!") return redirect('home') # 或者直接返回403禁止访问页面 # return HttpResponseForbidden("你没有权限执行此操作") if request.method == 'GET': form = EmployeeForm(instance=emp_record) return render(request, 'update.html', {'form': form}) else: form = EmployeeForm(request.POST, instance=emp_record) if form.is_valid(): form.save() # 可选:如果修改了员工姓名/邮箱,同步更新User的对应字段 # request.user.first_name = form.cleaned_data['emp_first_name'] # request.user.last_name = form.cleaned_data['emp_last_name'] # request.user.email = form.cleaned_data['email'] # request.user.save() messages.success(request, "员工记录更新成功!") return redirect('detail', id=id) messages.error(request, "更新失败,请检查输入内容是否合法!") return render(request, 'update.html', {'form': form})
额外优化:隐藏不属于当前用户的更新链接
在首页模板(home.html)中,只给当前登录用户显示自己的更新链接,避免无效操作:
{% for emp in employees %} <tr> <td>{{ emp.emp_first_name }} {{ emp.emp_last_name }}</td> <td>{{ emp.department }}</td> <!-- 其他字段展示 --> <td> <a href="{% url 'detail' emp.emp_id %}">查看详情</a> <!-- 仅当前用户能看到自己的更新链接 --> {% if emp.user == request.user %} <a href="{% url 'update' emp.emp_id %}">更新记录</a> {% endif %} </td> </tr> {% endfor %}
无需修改模型的替代方案(不推荐)
如果暂时不想修改数据库模型,可以通过用户名规则来匹配,但这种方式存在漏洞(比如员工姓名修改后用户名不同步):
修改update视图的验证逻辑:
@login_required(login_url='loginuser') def update(request, id): try: emp_record = Employee.objects.get(pk=id) except Employee.DoesNotExist: messages.error(request, "该员工记录不存在!") return redirect('home') # 按照new视图的规则生成预期用户名 def remove(string): return string.replace(" ", "") expected_username = remove(emp_record.emp_first_name) + remove(emp_record.emp_last_name) + str(emp_record.emp_id) if request.user.username != expected_username: messages.error(request, "你没有权限修改这条记录!") return redirect('home') # 后续更新逻辑和之前一致
内容的提问来源于stack exchange,提问作者mayank gupta
相关产品推荐
相关产品推荐

