You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何限制用户仅能访问指定动态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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:03:14