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
相关产品推荐
相关产品推荐

