【发布时间】: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