如何在Django认证用户间实现项目共享与访问控制
实现Django项目的多用户共享与访问控制
嘿,这个协作类需求太常见了!我之前做过类似的功能,给你一步步拆解怎么落地:
1. 修改Project模型(核心改动)
你原来的account是单外键,只能绑定一个用户,现在要改成区分项目所有者+多用户共享的结构,分两种场景适配:
场景1:仅需基础共享(无细分权限)
直接用ManyToManyField添加共享用户字段,同时把原account重命名为owner,语义更清晰:
from django.contrib.auth.models import User from django.db import models class Project(models.Model): name = models.CharField(max_length=255, default='') description = models.CharField(max_length=255, default='') # 注意:created_at应该用auto_now_add(仅创建时赋值),原auto_now会每次更新都修改时间,不符合创建时间的定义 created_at = models.DateTimeField(auto_now_add=True, null=True) updated_at = models.DateTimeField(auto_now=True, null=True) is_active = models.IntegerField(default=1, null=True) # 项目所有者,关联创建该项目的用户 owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owned_projects', null=True) # 共享给其他用户,blank=True允许项目暂时无共享用户 shared_users = models.ManyToManyField(User, related_name='shared_projects', blank=True)
场景2:需要细分权限(只读/编辑/管理员)
如果要给不同共享用户设置差异化权限,就得用**中间模型(through)**存储权限信息:
# 先定义共享权限的中间表 class ProjectShare(models.Model): PERMISSION_CHOICES = ( ('read', '只读'), ('edit', '编辑'), ('admin', '管理员'), ) project = models.ForeignKey(Project, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) permission = models.CharField(max_length=10, choices=PERMISSION_CHOICES, default='read') shared_at = models.DateTimeField(auto_now_add=True) # 修改Project模型 class Project(models.Model): # 保留其他字段... owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owned_projects', null=True) # 通过中间表关联共享用户,支持权限细分 shared_users = models.ManyToManyField(User, through=ProjectShare, related_name='shared_projects', blank=True)
2. 数据库迁移
修改模型后,执行以下命令更新数据库:
python manage.py makemigrations python manage.py migrate
提示:原
account字段的历史数据会自动迁移到owner字段,不用担心数据丢失。
3. 实现共享功能的视图与前端
共享项目的视图(仅所有者可操作)
写一个视图处理“共享给指定用户”的逻辑,确保只有项目创建者能执行共享:
from django.shortcuts import get_object_or_404, redirect, render from django.contrib.auth.decorators import login_required from django.http import HttpResponseForbidden from .models import Project, ProjectShare @login_required def share_project(request, project_id): # 校验当前用户是项目所有者 project = get_object_or_404(Project, id=project_id, owner=request.user) if request.method == 'POST': target_username = request.POST.get('username') permission = request.POST.get('permission', 'read') try: target_user = User.objects.get(username=target_username) # 避免重复共享同一用户 if not ProjectShare.objects.filter(project=project, user=target_user).exists(): ProjectShare.objects.create( project=project, user=target_user, permission=permission ) # 共享成功后跳回项目详情页 return redirect('project_detail', project_id=project.id) except User.DoesNotExist: # 处理用户不存在的情况,返回提示 return render(request, 'share_project.html', { 'project': project, 'error': '该用户不存在,请检查用户名' }) # GET请求返回共享表单 return render(request, 'share_project.html', {'project': project})
前端共享表单(share_project.html)
简单的表单让用户输入目标用户名和权限:
{% extends 'base.html' %} {% block content %} <h2>共享项目: {{ project.name }}</h2> {% if error %} <p style="color: red;">{{ error }}</p> {% endif %} <form method="post"> {% csrf_token %} <div style="margin: 10px 0;"> <label>目标用户名:</label> <input type="text" name="username" required style="margin-left: 10px;"> </div> <div style="margin: 10px 0;"> <label>权限:</label> <select name="permission" style="margin-left: 10px;"> <option value="read">只读</option> <option value="edit">编辑</option> <option value="admin">管理员</option> </select> </div> <button type="submit">确认共享</button> </form> {% endblock %}
4. 实现访问控制逻辑
在所有涉及项目访问的视图中,添加权限校验:
from django.shortcuts import get_object_or_404 from django.http import HttpResponseForbidden def project_detail(request, project_id): project = get_object_or_404(Project, id=project_id) # 权限判断:要么是所有者,要么是共享用户 is_owner = request.user == project.owner is_shared_user = request.user in project.shared_users.all() if not is_owner and not is_shared_user: return HttpResponseForbidden("你没有访问该项目的权限") # 正常返回项目详情 return render(request, 'project_detail.html', {'project': project})
如果用了细分权限,比如判断是否有编辑权限:
def edit_project(request, project_id): project = get_object_or_404(Project, id=project_id) # 所有者默认拥有所有权限,共享用户需要检查权限等级 if request.user == project.owner: pass else: share_record = ProjectShare.objects.filter( project=project, user=request.user, permission__in=['edit', 'admin'] ).first() if not share_record: return HttpResponseForbidden("你没有编辑该项目的权限") # 处理编辑逻辑...
这样一套流程下来,你就能实现完整的项目共享和访问控制功能,还能根据需求扩展更多权限类型~
内容的提问来源于stack exchange,提问作者Zain Khan
相关产品推荐
相关产品推荐

