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

基于Django实现特定用户查看特定文件的方案咨询

Hey there! Let's walk through how to build this document access control feature in Django— I’ve implemented similar systems before, so here’s a practical, step-by-step approach that fits your requirements:

1. Model Design: Track Documents and Access Permissions

First, we need to model our data to link documents with their allowed viewers. We’ll use a Document model for the uploaded files, and a join table (DocumentShare) to track which users have been granted access (this lets us add metadata like share timestamps later if needed):

from django.db import models
from django.contrib.auth.models import User

class Document(models.Model):
    title = models.CharField(max_length=255)
    file = models.FileField(upload_to='documents/')  # Stores files in MEDIA_ROOT/documents/
    uploader = models.ForeignKey(User, on_delete=models.CASCADE, related_name='uploaded_docs')
    created_at = models.DateTimeField(auto_now_add=True)

    # Link to users allowed to view this document (via our join table)
    allowed_viewers = models.ManyToManyField(User, through='DocumentShare', related_name='accessible_docs')

    # Helper method to check if a user can access this document
    def is_accessible_by(self, user):
        # Uploader always has access
        if user == self.uploader:
            return True
        # Check if the user is in the allowed viewers list
        return self.allowed_viewers.filter(id=user.id).exists()

class DocumentShare(models.Model):
    document = models.ForeignKey(Document, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    shared_at = models.DateTimeField(auto_now_add=True)
    # Optional: Add a permission_type field if you want to support edit access later
    # permission_type = models.CharField(max_length=20, choices=[('view', 'View'), ('edit', 'Edit')], default='view')
2. Add Share Functionality

Next, let’s build a view that lets document uploaders share files with specific users (by email or user ID):

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 Document, DocumentShare
from django.contrib.auth.models import User

@login_required
def share_document(request, doc_id):
    document = get_object_or_404(Document, id=doc_id)
    
    # Only the uploader can share the document
    if request.user != document.uploader:
        return HttpResponseForbidden("You don't have permission to share this document.")

    if request.method == 'POST':
        # Get the user to share with (you can use user ID instead of email if preferred)
        target_email = request.POST.get('user_email')
        try:
            target_user = User.objects.get(email=target_email)
            # Avoid duplicate shares
            if not DocumentShare.objects.filter(document=document, user=target_user).exists():
                DocumentShare.objects.create(document=document, user=target_user)
            return redirect('document_detail', doc_id=document.id)
        except User.DoesNotExist:
            return render(request, 'share_document.html', {
                'document': document,
                'error': 'User with this email does not exist.'
            })
    
    return render(request, 'share_document.html', {'document': document})
3. Restrict Access in Views

Now, we need to ensure only authorized users can view document details or download files. Let’s use a class-based detail view as an example:

from django.views.generic import DetailView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseForbidden
from .models import Document

class DocumentDetailView(LoginRequiredMixin, DetailView):
    model = Document
    template_name = 'document_detail.html'
    context_object_name = 'document'

    def get_object(self, queryset=None):
        document = super().get_object(queryset)
        # Check if the user has access
        if not document.is_accessible_by(self.request.user):
            return HttpResponseForbidden("You don't have permission to view this document.")
        return document

For a function-based view (great for file downloads), it looks like this:

from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden, FileResponse
import os

@login_required
def download_document(request, doc_id):
    document = get_object_or_404(Document, id=doc_id)
    if not document.is_accessible_by(request.user):
        return HttpResponseForbidden("You don't have permission to download this document.")
    
    # Serve the file (ensure MEDIA_URL is configured correctly)
    file_path = document.file.path
    if os.path.exists(file_path):
        return FileResponse(open(file_path, 'rb'), as_attachment=True, filename=document.title)
    return HttpResponseForbidden("File not found.")
4. Filter Document Lists for Users

Make sure users only see documents they can access in their list view:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import Document
from django.db.models import Q

@login_required
def document_list(request):
    # Show documents uploaded by the user OR shared with them
    accessible_docs = Document.objects.filter(
        Q(uploader=request.user) | Q(allowed_viewers=request.user)
    ).distinct()  # Avoid duplicates if a user is both uploader and shared with
    
    return render(request, 'document_list.html', {'documents': accessible_docs})
5. Bonus Tips for Polish
  • Add Notifications: When a document is shared with a user, send them an email using Django’s send_mail function.
  • Revoke Access: Build a view to delete DocumentShare records so uploaders can revoke access later.
  • Permission Levels: Extend the DocumentShare model with a permission_type field (e.g., 'view' vs 'edit') if you need to support more granular access.
  • Template Checks: In your templates, only show the "Share" button to the document’s uploader:
    {% if user == document.uploader %}
        <a href="{% url 'share_document' document.id %}" class="btn">Share Document</a>
    {% endif %}
    

内容的提问来源于stack exchange,提问作者biagio dipalma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:08:12