Django实现多文件上传与用户关联存储至数据库的方案
解决多用户文件上传时关联用户的问题
看起来你现在的核心需求是让每个上传的文件记录都绑定到对应的上传用户,避免多用户使用时出现文件混淆的情况。咱们一步步来调整代码解决这个问题:
1. 修正文件模型的关联字段(models.py)
你当前的files模型里owner用了OneToOneField,这意味着一个用户只能关联一个文件,完全不符合多文件上传的场景。得改成ForeignKey,这样一个用户可以拥有多条文件记录。另外注意你自定义了users模型,但代码里写的是User,这里要改成你自己的users模型:
from django.db import models class users(models.Model): person_name = models.CharField(max_length=50, null=False, blank=True, verbose_name="name") person_surname = models.CharField(max_length=50, null=False, blank=True, verbose_name="surname") email = models.CharField(max_length=100, null=False, blank=True, verbose_name='email') user_name = models.CharField(max_length=30, null=False, blank=True, verbose_name="username") user_password = models.CharField(max_length=35, null=False, blank=True, verbose_name="password") class files(models.Model): # 改成ForeignKey,允许一个用户对应多个文件,related_name改成更直观的名称 owner = models.ForeignKey(users, related_name="uploaded_files", on_delete=models.CASCADE) description = models.CharField(max_length=255, blank=True) excelFile = models.FileField(upload_to='upload/%Y/%m/%d',null=False, blank=True,) wordFile = models.FileField(upload_to='upload/%Y/%m/%d',null=False, blank=True,) txtEmailFile = models.FileField(upload_to='upload/%Y/%m/%d',null=False, blank=True,) txtContentFile = models.FileField(upload_to='upload/%Y/%m/%d',null=False, blank=True,) attachmentFile = models.FileField(upload_to='upload/%Y/%m/%d',null=False, blank=True,)
2. 调整表单配置(forms.py)
因为owner字段不需要用户在前端表单里选择,而是后台自动绑定当前登录用户,所以我们保持原有表单字段即可,或者明确排除owner字段(后者更清晰):
from django import forms from .models import files class DocumentForm(forms.ModelForm): class Meta: model = files fields = ('description', 'excelFile', 'wordFile', 'txtEmailFile', 'txtContentFile', 'attachmentFile') # 也可以用 exclude = ['owner'],两种写法效果一致
3. 在视图中绑定当前用户(views.py)
当表单验证通过后,不要直接调用form.save(),而是先创建实例但不提交到数据库(commit=False),然后给实例的owner字段赋值为当前登录的用户,最后再保存到数据库:
from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from .forms import DocumentForm @login_required(login_url="login") def sendmail(request): if request.method == 'POST': form = DocumentForm(request.POST, request.FILES) if form.is_valid(): # 先创建实例但不提交数据库 file_instance = form.save(commit=False) # 绑定当前登录的用户(注意:要确保你的认证系统用的是自定义的users模型,否则这里需要调整) file_instance.owner = request.user # 现在将实例保存到数据库 file_instance.save() return redirect('sendmail') else: form = DocumentForm() return render(request, 'sendmail.html')
额外注意事项
- 如果你用的是Django自带的认证系统而非自定义的
users模型,那要把models.py里的owner = models.ForeignKey(users, ...)改成owner = models.ForeignKey(User, ...),并且导入from django.contrib.auth.models import User。 - 若使用自定义用户模型,一定要在
settings.py里配置:AUTH_USER_MODEL = '你的应用名.users',否则request.user可能不是你自定义的users实例,会导致绑定失败。 - 修改模型后必须执行数据库迁移:运行
python manage.py makemigrations和python manage.py migrate,否则数据库不会更新字段。
这样调整后,每个上传的文件记录都会自动关联到当前登录的用户,再也不用担心多用户上传的文件混淆啦!
内容的提问来源于stack exchange,提问作者devilsgrin
相关产品推荐
相关产品推荐

