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

Django表单字段过滤问题:无法筛选外键仅展示用户创建内容

Django表单过滤器无法显示当前用户企业数据的问题修复

问题场景

表单的company_client字段需仅展示当前登录用户创建的企业,但添加ClientCompany.objects.filter(user=self.user)过滤后,字段无任何选项;移除过滤器则显示所有用户的企业。

相关代码

forms.py

class ClientContractForm(ModelForm):
    clausules = forms.CheckboxSelectMultiple()
    work_order = forms.CharField(required=True, label='Ordem de serviço',
                                 widget=forms.TextInput(attrs={'class': 'form-control'}))
    contract_name = forms.CharField(required=True, label='Nome do contrato', widget=forms.TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Insira o nome do seu contrato'}))
    address = forms.CharField(required=True, label='Endereço do contrato', widget=forms.TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Insira o endereço do contrato'}))
    installments = forms.CharField(required=True, label='Parcelas', widget=forms.TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Insira o número de parcelas do contrato'}))
    items = forms.CharField(required=True, label='Itens do contrato', widget=forms.TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Insira o número de parcelas do contrato'}))

    class Meta:
        model = ClientContract
        fields = ['work_order', 'contract_name', 'address', 'installments', 'items', 'clausules', 'company_client']

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(ClientContractForm, self).__init__(*args, **kwargs)
        self.fields['clausules'].queryset = Clausule.objects.filter(user=self.user)
        self.fields['items'].queryset = Item.objects.filter(user=self.user)
        self.fields['work_order'].queryset = Contract.objects.filter(user=self.user)
        self.fields['company_client'].queryset = ClientCompany.objects.filter(user=self.user)

models.py

class ClientContract(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    work_order = models.ForeignKey(Contract, on_delete=models.CASCADE, null=True, blank=True)
    contract_name = models.CharField(max_length=60)
    address = models.TextField(blank=True, null=True)

    # Value related information
    total_value = models.DecimalField(blank=True, null=True, max_digits=12, decimal_places=2)
    installments = models.IntegerField(null=True, blank=True)

    # Items and clausules of the contract
    items = models.ManyToManyField(Item, blank=True, null=True)
    clausules = models.ManyToManyField(Clausule, blank=True, null=True)

    # Company associated with the contract
    company_client = models.ForeignKey(ClientCompany,blank=True, null=True, on_delete=models.PROTECT)

    def __str__(self):
        return self.contract_name

views.py

"""
ADD A NEW CONTRACT
"""
@login_required
def new_client_contract(request):
    form = ClientContractForm(request.POST or None, request.FILES or None)

    if form.is_valid():
        form = form.save(commit=False)
        form.user = request.user
        form.save()
        return redirect('list_generated_contracts')
    return render(request, 'client_contract_form.html', {'form': form})

问题根源

视图中创建ClientContractForm实例时,未传入当前登录用户user参数。表单的__init__方法虽然通过kwargs.pop('user', None)获取用户,但由于视图没传值,self.user为None,导致过滤条件变成user=None,自然查不到任何数据。

修复步骤

1. 修改视图,传入当前用户

更新views.py中创建表单的代码,添加user=request.user参数:

@login_required
def new_client_contract(request):
    # 新增user=request.user参数
    form = ClientContractForm(request.POST or None, request.FILES or None, user=request.user)

    if form.is_valid():
        form = form.save(commit=False)
        form.user = request.user
        form.save()
        return redirect('list_generated_contracts')
    return render(request, 'client_contract_form.html', {'form': form})

2. 可选:添加容错处理(避免用户为空时出错)

在forms.py的__init__方法中,先判断self.user是否存在,再执行过滤,防止空值导致的异常:

def __init__(self, *args, **kwargs):
    self.user = kwargs.pop('user', None)
    super(ClientContractForm, self).__init__(*args, **kwargs)
    if self.user:
        self.fields['clausules'].queryset = Clausule.objects.filter(user=self.user)
        self.fields['items'].queryset = Item.objects.filter(user=self.user)
        self.fields['work_order'].queryset = Contract.objects.filter(user=self.user)
        self.fields['company_client'].queryset = ClientCompany.objects.filter(user=self.user)

验证

修改后,表单的company_client字段会正确加载当前登录用户创建的所有企业,过滤逻辑生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:54:58