django inline_formset - 为基于另一个字段的字段设置查询集

django inline_formset - set queryset for a field based on another field

我有三个模型 - Item、Invoice 和 InvoiceItem。每个项目可能有一个或多个与其关联的税组(名称、税率等)。

class Item(models.Model):
    name=models.CharField(max_length=100, unique=True, db_index=True)
    tax_group=models.ManyToManyField(TaxGroup)

class Invoice(models.Model):
    number=models.CharField("invoice number",max_length=20,unique=True,default=invoiceIncrement,  )
    date=models.DateField("invoice date")
    contact=models.ForeignKey(Contact, on_delete=models.CASCADE)
    total=models.DecimalField(decimal_places=2, max_digits=12)

class InvoiceItem(models.Model):
    invoice=models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='invoice_items')
    item=models.ForeignKey(Item, on_delete=models.CASCADE)
    tax=models.ForeignKey(TaxGroup, on_delete=models.CASCADE)
    quantity=models.PositiveIntegerField()
    rate=models.DecimalField(decimal_places=2, max_digits=12)
    total=models.DecimalField(decimal_places=2, max_digits=12,null=True)

我使用以下表格制作了一个 inline_formset,如下所示。

class InvoiceItemForm(forms.ModelForm):
    class Meta:
        model=InvoiceItem
        exclude=()

ItemInlineFormSet = inlineformset_factory(Invoice, 
    InvoiceItem, form=InvoiceItemForm, 
    extra=1, can_delete=False,
      validate_min=True, min_num=1)

现在,我需要确保对应于表单集中的每个选定项目,字段tax 应该只包含与他们相关的税收。

对于客户端,我 添加了一些 ajax 代码以根据每个项目字段的选择填充税字段。

如何确保所选的税字段是 Item 对象的 ManyToMany 值之一?

我已经尝试指定一个自定义表单集来为字段设置一个查询集,比如

class BaseItemFormSet(forms.BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super(BaseItemFormSet, self).__init__(*args, **kwargs)

        for form in self.forms:
            form.fields['tax'].queryset = Item.objects.get(form.fields['item']).tax_group.all()

这行不通(而且我不确定这是否是正确的方法)。

我是否需要在表单集中使用 clean() 方法来验证每个字段?

请帮忙,

谢谢。

是 (back-end) 验证您需要对 InvoiceItemForm 上的税务字段进行自定义验证:

class InvoiceItemForm(forms.ModelForm):

    def clean_tax(self):
        selected_tax_group = self.cleaned_data['tax']
        # your custom validation (TaxGroup lookup and validation)
        is_valid_tax_group = False
        if not is_valid_tax_group
            raise forms.ValidationError("Invalid Tax Group selected")

        return data

    class Meta:
        model=InvoiceItem
        exclude=()

希望对您有所帮助!

这是我的做法。

def __init__(self, *args, **kwargs):
        super(InvoiceItemFormSet, self).__init__(*args, **kwargs)
        if self.data:
            i=0
            for form in self.forms:
                key = 'item-'+str(i)+'-item'
                if self.data[key]:
                    form.fields['tax'].queryset= Item.objects.get(id=self.data[key]).tax_group.all()
                i=i+1

(欢迎进行可能的简化)