如何在Django通用类视图中移除当前用户的下拉选项?
解决Django基于类视图下拉菜单排除当前用户的问题
嘿,这个需求挺典型的,我来给你两种靠谱的实现方式,你可以根据自己的情况选:
方法一:直接在视图中重写get_form方法
这种方式最简单,不用额外定义表单类,直接在TransferCreateView里修改字段的查询集就行,同时别忘了在form_valid里设置发送方:
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import CreateView from .models import Transfer, User class TransferCreateView(LoginRequiredMixin, CreateView): model = Transfer template_name = 'points/transfer_form.html' fields = ['receiver', 'message', 'amount'] def get_form(self, form_class=None): # 先调用父类方法获取默认表单 form = super().get_form(form_class) # 修改receiver字段的查询集,排除当前登录用户 form.fields['receiver'].queryset = User.objects.exclude(id=self.request.user.id) return form def form_valid(self, form): # 把当前登录用户设为转账的发送方 form.instance.sender = self.request.user return super().form_valid(form)
这里加了LoginRequiredMixin是为了确保只有登录用户才能访问这个页面,避免出现匿名用户导致的错误,非常建议加上。
方法二:自定义ModelForm(更适合复杂场景)
如果之后你的表单逻辑变复杂了,比如要加更多字段验证或者自定义样式,用自定义表单类会更清晰:
首先定义表单类:
from django import forms from .models import Transfer, User class TransferForm(forms.ModelForm): class Meta: model = Transfer fields = ['receiver', 'message', 'amount'] def __init__(self, *args, **kwargs): # 从参数里取出当前用户,记得要先pop出来再调用父类初始化 self.current_user = kwargs.pop('user') super().__init__(*args, **kwargs) # 排除当前用户作为接收方选项 self.fields['receiver'].queryset = User.objects.exclude(id=self.current_user.id)
然后修改视图类,指定form_class并传递当前用户给表单:
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import CreateView from .models import Transfer from .forms import TransferForm class TransferCreateView(LoginRequiredMixin, CreateView): model = Transfer template_name = 'points/transfer_form.html' form_class = TransferForm def get_form_kwargs(self): # 获取默认的表单参数,然后把当前用户加进去 kwargs = super().get_form_kwargs() kwargs['user'] = self.request.user return kwargs def form_valid(self, form): form.instance.sender = self.request.user return super().form_valid(form)
为什么这两种方式可行?
- 第一种方式直接在视图层动态修改表单字段的
queryset,适合简单场景,代码量少; - 第二种方式把表单的逻辑封装在表单类里,符合Django的MVC思想,后续扩展更方便。
两种方式都能实现“不让当前登录用户出现在接收方下拉菜单”的需求,同时在表单验证通过时正确设置发送方。
内容的提问来源于stack exchange,提问作者sb9
相关产品推荐
相关产品推荐

