【问题标题】:Django: How to verify a form whose fields are generated from a queryset in the forms __init__ method?Django:如何验证其字段是从表单 __init__ 方法中的查询集生成的表单?
【发布时间】:2020-04-10 14:37:59
【问题描述】:

我在想出一个好的解决方案来验证其字段设置在其 init 方法中的表单时遇到了一些麻烦。


快速解释我的模型:每个产品都应该有变体,每个变体又具有多个 VariationOptions。

  • 每个产品都可以有多个变体,例如“颜色”或“材质”
  • 变体可以有多个 VariationOptions (ManyToMany-Relation),例如“red”或“concrete”

在渲染 AddToCartForm 时,每个 Variation 对应一个 ChoiceField,其中 VariationOptions 用作所述 ChoiceField 的选项。 (见forms.py)


由于每个产品都可以有不同的变体,因此也可以有不同的字段,因此必须从包含产品变体 (views.py) 的查询集动态生成 AddToCart 表单,或者至少这是我现在的想法。

我的问题:

  • 如何验证这种表单?
  • 您有没有更好的方法来实现相同的想法?

非常感谢您的帮助。提前致谢!


这是我的简化代码:

MODELS.PY

class Product(models.Model):
    ..

class Variation(models.Model):
    name     =  models.CharField()
    product  =  models.ForeignKey(Product, on_delete=models.CASCADE, related_name='variations')
    options  =  models.ManyToManyField(VariationOption, blank=True)

class VariationOption(models.Model):
    value = CharField()

FORMS.PY

class AddToCart(forms.Form):
    quantity    = forms.PositiveIntegerField()

    # for every variation get all its choices and add new ChoiceField to form
    def __init__(self, variations, *args, **kwargs):
        super(AddToCart, self).__init__(*args, **kwargs)
        for variation in variations: 
            CHOICES = []
            choices_list = list(variation.options.all())
            for choice in choices_list:
                CHOICES.append(tuple((choice.value, choice.value)))
            self.fields[variation.name] = forms.ChoiceField(choices=CHOICES)

VIEWS.PY

def render_product(request):
    ...
    variations = list(Variation.objects.prefetch_related('options').filter(product=product))
    add_to_cart_form = AddToCartForm(variations=variations)
    return render(...)

@require_POST
def add_to_cart_view(request):
    form = AddToCartForm(request.POST) # This isn't working. I see why, but know no other way.
    if form.is_valid():
        ....

【问题讨论】:

    标签: python django django-models django-forms django-views


    【解决方案1】:

    更新

    万一以后有人遇到这个问题并且有同样的问题:显然您可以实例化一个表单并在同一步骤中将其传递 POST 数据。

    使用这样的表格:

    FORMS.PY

    class SomeForm(forms.Form):
        field    = forms.PositiveIntegerField() #optional
    
        def __init__(self, variable, *args, **kwargs):
            super(AddToCart, self).__init__(*args, **kwargs)
            # do something with variable, generate fields or choices etc etc
    

    这将起作用:

    form = SomeForm(variable=something, data=request.POST)
    if form.is_valid():
        # This will work when POST is actually valid
    

    表单会将变量传递给它的 __init__ 方法,执行任何实现的逻辑,然后绑定到 POST 数据。验证现在可以正常工作。

    【讨论】:

      猜你喜欢
      • 2018-06-01
      • 2016-12-20
      • 1970-01-01
      • 1970-01-01
      • 2018-11-04
      • 2017-11-13
      • 1970-01-01
      • 1970-01-01
      • 2019-03-13
      相关资源
      最近更新 更多