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

Django ModelForm如何自动填充当前用户并过滤收件人选项

Django 站内消息功能优化实现方案

你需要修改表单、视图两个核心部分,即可实现发件人自动填充、收件人排除当前用户的需求,具体修改如下:

1. 修改表单文件 Forms.py

核心改动:

  • 移除用户可编辑的zender(发件人)字段,避免前端手动选择
  • 重写表单初始化方法,接收当前登录用户参数,过滤收件人下拉选项
  • 增加字段校验逻辑,拦截恶意构造的自发自收请求
class Mailsythemform(forms.ModelForm):
    class Meta:
        model = Mailsysthem
        # 移除zender字段,该字段由后端自动赋值
        fields = ['ontvanger', 'subject', 'text']

    def __init__(self, *args, **kwargs):
        # 提取传入的当前用户参数,避免传给父类表单报错
        current_user = kwargs.pop('current_user', None)
        super().__init__(*args, **kwargs)
        self.current_user = current_user
        if current_user:
            # 收件人下拉列表排除当前登录用户
            self.fields['ontvanger'].queryset = CustomUser.objects.exclude(id=current_user.id)

    def clean_ontvanger(self):
        # 额外校验层,防止恶意构造请求给自己发消息
        receiver = self.cleaned_data.get('ontvanger')
        if self.current_user and receiver.id == self.current_user.id:
            raise forms.ValidationError("不允许选择自己作为收件人")
        return receiver

2. 修改视图文件 views.py

核心改动:

  • 修复原代码缩进错误(原代码表单校验逻辑写在了POST请求判断外,GET请求会触发不必要的校验报错)
  • 实例化表单时传入当前登录用户参数
  • 表单校验通过后,自动给发件人字段赋值为当前登录用户,再存入数据库
def mailEMployee(request):
    # 未登录用户跳转登录页,如果你配置了全局登录校验可删除这段
    if not request.user.is_authenticated:
        return redirect('login')

    # 查询当前用户的收件、发件记录,可根据你的业务加软删除过滤
    received_mails = Mailsysthem.objects.filter(ontvanger=request.user, solftdelete=False)
    sent_mails = Mailsysthem.objects.filter(zender=request.user, solftdelete=False)

    if request.method == 'POST':
        # 传入当前用户参数初始化表单
        form = Mailsythemform(request.POST, request.FILES, current_user=request.user)
        if form.is_valid():
            # 先不写入数据库,补全发件人字段
            mail_obj = form.save(commit=False)
            mail_obj.zender = request.user
            mail_obj.save()
            return redirect('mail')
    else:
        # GET请求初始化空表单,同样传入当前用户
        form = Mailsythemform(current_user=request.user)

    context = {
        'form': form,
        'receiver': received_mails,
        # 注意原代码这里sender.all写法错误,QuerySet调用all需要加括号
        'sender': sent_mails.all,
        'mail': received_mails,
        # 原代码中查询user的逻辑冗余,request.user本身就是当前用户实例,可直接在模板使用
    }
    return render(request, 'emp/mail.html', context)

补充说明

  • 模板部分不需要额外改动,渲染表单时只会显示收件人、主题、正文三个输入项,发件人字段完全由后端自动填充,用户无法篡改
  • 如果你需要给发件人设置初始值但保留字段只读,也可以不把zender从fields里移除,而是在初始化时设置self.fields['zender'].initial = current_user,同时加self.fields['zender'].disabled = True,但直接移除字段的方式安全性更高
  • 原代码中CustomUser.objects.filter(email=request.user)逻辑有误,request.user是用户对象不是邮箱字符串,这个查询完全多余,直接使用request.user即可获取当前登录用户信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:36:25