如何在Django表单中获取当前Record模型ID以过滤BDC查询集?
问题描述
在实现查询集过滤时遇到困难,无法获取表单对应的当前Record模型ID,具体是在forms.py的AddRecordForm中,需要根据当前Record的ID匹配BDC模型的ref字段,从而填充多选组件的选项:
queryset=BDC.objects.filter(ref = ???当前Record模型的ID??? ).values_list('model')
现有代码
views.py
def update_record(request, pk): if request.user.is_authenticated: current_record = Record.objects.get(id=pk) form = AddRecordForm(request.POST or None, instance=current_record) if form.is_valid(): form.save() messages.success(request, "Record Has Been Updated!") return redirect('home') return render(request, 'update_record.html', {'form':form}) else: messages.success(request, "You Must Be Logged In...") return redirect('home')
forms.py
class AddRecordForm(forms.ModelForm): testrever = forms.ModelMultipleChoiceField(widget=forms.widgets.SelectMultiple, queryset=BDC.objects.filter(ref = ???当前Record模型的ID???).values_list('model')) class Meta: model = Record exclude = ("user",) class BDCform(forms.ModelForm): ref = forms.CharField(required=False, widget=forms.widgets.TextInput(attrs={"placeholder":"First Name", "class":"form-control"}), label="") model = forms.CharField(required=False, widget=forms.widgets.TextInput(attrs={"placeholder":"Last Name", "class":"form-control"}), label="") class Meta: model = BDC exclude = ("user",)
models.py
class Record(models.Model): id = models.CharField(primary_key=True, max_length=50) testrever = models.JSONField(max_length=500) def __str__(self): return (f"{self.first_name} {self.last_name}") class BDC(models.Model): ref = models.CharField(max_length=50) model = models.CharField(max_length=50)
解决方案
表单定义阶段无法直接获取当前Record实例的ID,需通过动态修改字段查询集实现需求,步骤如下:
- 修改AddRecordForm的初始化方法
将testrever字段初始查询集设为空,在__init__方法中根据传入的Record ID或实例动态过滤BDC数据:
class AddRecordForm(forms.ModelForm): testrever = forms.ModelMultipleChoiceField( widget=forms.widgets.SelectMultiple, queryset=BDC.objects.none() # 初始为空查询集 ) class Meta: model = Record exclude = ("user",) def __init__(self, *args, **kwargs): # 取出传入的record_id参数,若无则从instance中获取 record_id = kwargs.pop('record_id', None) super().__init__(*args, **kwargs) # 优先使用表单关联的Record实例ID if self.instance and self.instance.pk: record_id = self.instance.pk # 根据Record ID过滤BDC,生成多选组件的选项 if record_id: # 使用flat=True确保返回扁平的字符串列表,适配ModelMultipleChoiceField要求 self.fields['testrever'].queryset = BDC.objects.filter(ref=record_id).values_list('model', flat=True) def clean_testrever(self): # 将多选结果转为列表,适配Record模型的JSONField类型 return list(self.cleaned_data['testrever'])
- 更新视图中的表单初始化逻辑
在update_record视图中初始化表单时,传入当前Record的ID(或直接依赖instance):
def update_record(request, pk): if request.user.is_authenticated: current_record = Record.objects.get(id=pk) # 传入record_id参数,或仅传instance即可(表单会自动读取instance.pk) form = AddRecordForm(request.POST or None, instance=current_record, record_id=pk) if form.is_valid(): form.save() messages.success(request, "Record Has Been Updated!") return redirect('home') return render(request, 'update_record.html', {'form':form}) else: messages.success(request, "You Must Be Logged In...") return redirect('home')
关键说明
ModelMultipleChoiceField要求查询集返回可迭代的单个值或模型实例,因此使用values_list('model', flat=True)生成扁平的字符串列表;- 新增
clean_testrever方法将多选结果转为列表,确保能正确存入Record模型的JSONField字段。
内容的提问来源于stack exchange,提问作者Nico44044
相关产品推荐
相关产品推荐

