【问题标题】:Django - form_valid() takes 2 positional arguments but 5 were given - Multiple formsDjango - form_valid() 接受 2 个位置参数,但给出了 5 个 - 多种形式
【发布时间】:2021-04-09 03:29:16
【问题描述】:

我是使用 Django 的新手,我想使用 CreateView 保存 4 种不同的表单。我可以保存其中的 3 个:

  • 产品形式
  • 产品成本表
  • 产品价格表

但是对于产品库存表格,我收到此错误:form_valid() 接受 2 个位置参数,但给出了 5 个。

产品库存表:

class ProdInvForm2(ModelForm):


    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Row(
                Column('invmax', css_class='form-group col-md-6 mb-0'),
                Column('invmin', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            
        )

    class Meta:
        model = ProdInv
        # fields = ('invmin', 'invmax')
        widgets = {
            
            'invmax': NumberInput(
                attrs={
                    'placeholder': 'Inventario Maximo',
                }
            ),
            'invmin': NumberInput(
                attrs={
                    'placeholder': 'Inventario Minimo',
                }
            ),

        }
        # esto es para excluir campos que no quieres que aparezcan
        #, 'invact', 'invord', 'invres'
        exclude = ['user_updated', 'user_creation', 'prod', 'invact', 'invord', 'invres']

产品库存模型:

class ProdInv(BaseModel):
    prod = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='Producto')
    invact = models.IntegerField(default=0, null=True, blank=True, verbose_name='Inventario Actual')
    invres = models.IntegerField(default=0, null=True, blank=True, verbose_name='Inventario Reservado')
    invord = models.IntegerField(default=0, null=True, blank=True, verbose_name='Inventario Ordenado')
    invmax = models.IntegerField(default=0, blank=True, verbose_name='Inventario Maximo')
    invmin = models.IntegerField(default=0, blank=True, verbose_name='Inventario Minimo')


    def toJSON(self):
        item = model_to_dict(self, exclude=['user_creation', 'user_updated'])
        item['prod'] = self.prod.toJSON()
        return item

    def __str__(self):
        return self.prod.name
    

    class Meta:
        verbose_name = 'Inventario de Producto'
        verbose_name_plural = 'Inventario de Productos'
        ordering = ['id']

创建视图:

class ProductCreateView(LoginRequiredMixin, ValidatePermissionRequiredMixin, CreateView):
    model = Product
    form_class = ProductForm
    template_name = 'product/create.html'
    success_url = reverse_lazy('erpInv:product_list')
    permission_required = 'erpAdm.add_product'
    url_redirect = success_url

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    

    def post(self, request, *args, **kwargs):
        data = {}

        try:
            action = request.POST['action']
            if action == 'add':

                AttrValueFormSet = formset_factory(AttrValueForm, can_delete=True, extra=1)
                formprod = ProductForm(request.POST)
                formcost = ProdCostForm(request.POST)
                formprice = ProdPriceForm(request.POST)
                formprodinv = ProdInvForm2(request.POST)
                AV_formset = AttrValueFormSet(request.POST)
               
                with transaction.atomic():
                    if formprod.is_valid() and formcost.is_valid() and formprice.is_valid() \
                            and formprodinv.is_valid():

                        return self.form_valid(formprod, formcost, formprice, formprodinv)
                    else:
                        return self.form_invalid(formprod, formcost, formprice, formprodinv)

            else:
                data['error'] = 'No ha ingresado a ninguna opción'
        except Exception as e:
            data['error'] = str(e)
            # acuerdate cuando es coleccion de elementos, hay que serializar con safe=flase
        return JsonResponse(data, safe=False)

    def form_valid(self, formprod, formcost, formprice, formprodinv):

        # hubo que cmentar e save del form, para que funcione el save()
        with transaction.atomic():
            prod = formprod.save(commit=True)
            print(prod.pk)
            price = formprice.save(commit=False)
            price.prod_id = prod.pk
            cost = formcost.save(commit=False)
            cost.prod_id = prod.pk
            print(cost)
            inv = formprodinv.save(commit=False)
            inv.prod_id = prod.pk
            print(inv)
            inv.save()
            cost.save()
            price.save()

        return super().form_valid(formprod, formcost, formprice, formprodinv)

    def form_invalid(self, formprod, formcost, formprice, formprodinv):

        return self.render_to_response(
            self.get_context_data(formprod=formprod.errors, formcost=formcost.errors, formprice=formprice.errors,
                                  formprodinv=formprodinv.errors))

        # Dont Know which one to use as return statement

        # return super().form_invalid(formprod=formprod.errors, formcost=formcost.errors, formprice=formprice.errors,
        #                       formprodinv=formprodinv.errors)

    def get_context_data(self, **kwargs):
        # AVForm = AttrValueForm(prefix='avprefix')
        AttrValueFormSet = formset_factory(AttrValueForm, can_delete=True, extra=1)
        context = super().get_context_data(**kwargs)
        context['title'] = 'Creación un Producto'
        context['entity'] = 'Productos'
        context['list_url'] = self.success_url
        context['action'] = 'add'
        context['formcost'] = ProdCostForm()
        context['formprice'] = ProdPriceForm(prefix='precio')
        context['formprodinv'] = ProdInvForm2(prefix='invent')

        # Next step try to use formset to save product attributes
        # context['AV_formset'] = AttrValueFormSet(prefix='avprefix')
        # context['avHelper'] = AVHelper()
        return context

我做了测试并评论“transaction.atomic()”。我能够保存到其他表单,但不知道为什么我在使用产品库存表单时遇到此问题。

希望有人能指出我做错了什么。

新年快乐

【问题讨论】:

  • return super().form_valid(formprod, formcost, formprice, formprodinv) 没有多大意义,因为基础 form_valid 采用 one 参数:一种形式,但只有 one 形式。
  • @WillemVanOnsem 我把它作为 StackOverflow 中另一篇关于使用 createview 保存倍数表单的文章的参考。但他们只使用了两种形式。

标签: django forms django-models


【解决方案1】:

为了解决我的问题,我将表单保存在 de def POST 中。而不是使用 form_valid()。

def post(self, request, *args, **kwargs): 数据 = {}

try:
    action = request.POST['action']
    if action == 'add':

        AttrValueFormSet = formset_factory(AttrValueForm, can_delete=True, extra=1)
        formprod = ProductForm(request.POST)
        formcost = ProdCostForm(request.POST)
        formprice = ProdPriceForm(request.POST)
        formprodinv = ProdInvForm2(request.POST)
        AV_formset = AttrValueFormSet(request.POST)
        

        with transaction.atomic():
            if formprod.is_valid() and formcost.is_valid() and formprice.is_valid() and formprodinv.is_valid():
                print('los form son validos')

                
                prod = formprod.save(commit=True)
                print(prod.pk)
                
                price = formprice.save(commit=False)
                print('precio')
                print(formprice.cleaned_data)
                price.prod_id = prod.pk
                

                cost = formcost.save(commit=False)
                print('costo')
                cost.prod_id = prod.pk

                inv = formprodinv.save(commit=False)
                print('Inventario')
                print(formprodinv.cleaned_data)
                

                inv.prod_id = prod.pk
                
                inv.save()

                cost.save()
                price.save()

           
            else:
                print('los forms NO son validos')
                return formprod.errors, formprice.errors, formcost.errors, formprodinv.errors


    else:
        data['error'] = 'No ha ingresado a ninguna opción'
except Exception as e:
    data['error'] = str(e)
    # acuerdate cuandp es coleccion de elementos, hay que serializar con safe=flase
return JsonResponse(data, safe=False)

【讨论】:

    猜你喜欢
    • 2021-05-04
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 2020-10-30
    相关资源
    最近更新 更多