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

Django用户文件上传权限问题:实现用户仅查看自身上传文件

解决Django中用户仅查看自身上传文件的问题

嘿,这个需求其实挺常见的,好在你已经在Document模型里关联了User外键,基础工作已经做好了,咱们只需要在视图和权限控制上做些调整就行,一步步来:

1. 确保文件上传时关联当前登录用户

首先得保证用户上传文件的时候,这个文件能和当前登录的用户绑定在一起。如果你的上传视图还没做这一步,赶紧加上:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import DocumentForm

@login_required  # 限制只有登录用户才能上传
def upload_document(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            # 先不保存到数据库,先关联用户
            document = form.save(commit=False)
            document.user = request.user  # 绑定当前登录用户
            document.save()  # 现在再保存
            return redirect('document_list')  # 跳转到文件列表页
    else:
        form = DocumentForm()
    return render(request, 'upload.html', {'form': form})

2. 修改文件列表视图,只返回当前用户的文件

之前的列表视图应该是取了所有Document.objects.all(),现在要改成只筛选当前用户的文件:

from django.contrib.auth.decorators import login_required
from .models import Document

@login_required
def document_list(request):
    # 关键:用filter过滤出当前用户的文件
    user_documents = Document.objects.filter(user=request.user)
    return render(request, 'document_list.html', {'documents': user_documents})

这样模板里拿到的documents就只有当前登录用户自己上传的文件了,直接遍历展示就行。

3. 可选但重要:防止用户直接通过URL访问他人文件

如果你的文件是存在媒体目录(MEDIA_ROOT)里的,默认情况下用户知道文件URL的话就能直接访问,这会有安全隐患。咱们可以写一个专门的视图来处理文件下载,先检查权限再返回文件:

from django.http import HttpResponse, Http404
from django.contrib.auth.decorators import login_required
from .models import Document
import os

@login_required
def download_document(request, doc_id):
    try:
        # 同时检查文件存在和用户权限
        document = Document.objects.get(id=doc_id, user=request.user)
    except Document.DoesNotExist:
        raise Http404("文件不存在或您没有访问权限")
    
    # 假设你的document字段存的是文件路径(如果是FileField的话用document.path)
    file_path = document.document
    if not os.path.exists(file_path):
        raise Http404("文件已被删除")
    
    # 返回文件给用户
    with open(file_path, 'rb') as f:
        response = HttpResponse(f.read(), content_type='application/octet-stream')
        response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"'
        return response

然后在urls.py里配置这个视图的路由,比如:

from django.urls import path
from . import views

urlpatterns = [
    # ...其他路由
    path('download/<int:doc_id>/', views.download_document, name='download_document'),
]

模板里的下载链接就改成指向这个路由:

{% for doc in documents %}
    <div class="document-item">
        <p>{{ doc.description }}</p>
        <a href="{% url 'download_document' doc.id %}">下载文件</a>
        <p>上传时间:{{ doc.uploaded_at }}</p>
    </div>
{% endfor %}

额外小提醒

  • 记得给所有涉及文件操作的视图加上@login_required装饰器,防止未登录用户访问。
  • 如果用了类视图(比如ListView),可以重写get_queryset方法来过滤用户:
    from django.views.generic import ListView
    from django.contrib.auth.mixins import LoginRequiredMixin
    from .models import Document
    
    class DocumentListView(LoginRequiredMixin, ListView):
        model = Document
        template_name = 'document_list.html'
        context_object_name = 'documents'
    
        def get_queryset(self):
            # 过滤当前用户的文件
            return Document.objects.filter(user=self.request.user)
    

这样一套操作下来,用户就只能看到自己上传的文件,也没法通过URL偷偷访问别人的文件啦~

内容的提问来源于stack exchange,提问作者Syed Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:22:12