#django #forms #django-models
#django #формы #django-модели
Вопрос:
Я новичок в использовании Django и хочу сохранить 4 разные формы с помощью CreateView. Я могу сохранить 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']
CreateView:
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()». Я смог сохранить в другие формы, но не знаю, почему у меня возникла эта проблема с формой инвентаризации товара.
Надеюсь, кто-нибудь сможет указать, что я делаю неправильно.
Приветствия и счастливого Нового года
Комментарии:
1.
return super().form_valid(formprod, formcost, formprice, formprodinv)
не имеет особого смысла, поскольку базаform_valid
принимает один параметр: форму, но только одну форму.2. @WillemVanOnsem Я взял это в качестве ссылки из другого сообщения в StackOverflow, о сохранении кратной формы с помощью createview. Но они использовали только 2 формы.
Ответ №1:
Чтобы решить мою проблему, я сохранил формы внутри de def POST. Вместо того, чтобы использовать form_valid().
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():
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)