Django: как сделать стандартную форму ввода для условной вставки ИЛИ обновления записей типа "многие-ко-многим"?
Я пытаюсь найти способ обновления или вставки новых записей типа "многие-ко-многим" из Product
в Order
через промежуточную модель ProductOrder
.
Я хочу иметь стандартную форму со всеми Products
и соответствующими количествами poQty
. Стандартная форма (предполагается, что всего в ней будет 4 продукта) используется для обновления существующих записей Order
. Если заказ имеет 2 Products
, связанных с ним, форма должна:
- включите дополнительные продукты, если
poQty>0
- изменить существующие продукты, если
poQty
изменился - ничего не делать, если несуществующие
Products
остаются стандартнымиpoQty=0
В настоящее время я получаю следующее сообщение об ошибке при попытке отправить форму:
{'id': ['Select a valid choice. That choice is not one of the available choices.']},
{'id': ['Select a valid choice. That choice is not one of the available choices.']},
{'id': ['Select a valid choice. That choice is not one of the available choices.']}]
Буду признателен за помощь в этом вопросе... СПАСИБО !
Дополнительные сведения:
models.py
class ProductClass(models.Model):
classDescription = models.CharField(max_length=255, verbose_name='Type', unique=True, null=True)
classPrint = models.BooleanField(default=True, verbose_name='Print?')
class Meta:
verbose_name_plural = 'Product Classes'
def __str__(self):
return self.classDescription
class Product(models.Model):
prodclassQuery = models.ForeignKey(ProductClass, on_delete=models.PROTECT, verbose_name='Product Class', default=1)
prodDescription = models.CharField(max_length=255, verbose_name='Product')
prodPrice = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='Price')
class Meta:
ordering = ['prodclassQuery', 'prodDescription']
def __str__(self):
return self.prodDescription
class Menu(models.Model):
menuActive = models.BooleanField(verbose_name='Active?', default=False)
menuDescription = models.CharField(max_length=255, verbose_name='Menu')
prodQuery = models.ManyToManyField(Product, verbose_name='Product')
class Meta:
ordering = ['menuDescription', ]
def __str__(self):
return self.menuDescription
class Order(models.Model):
orderDtOpen = models.DateTimeField(auto_now_add=True)
orderDtClose = models.DateTimeField(auto_now=True)
orderOpen = models.BooleanField(default=True, verbose_name='Open?')
orderTable = models.CharField(max_length=25, verbose_name='Table')
menuQuery = models.ForeignKey(Menu, on_delete=models.PROTECT, verbose_name='Menu', default=1)
prodQuery = models.ManyToManyField(Product, through='ProductOrder')
class ProductOrder(models.Model):
poOrder = models.ForeignKey(Order, on_delete=models.CASCADE, verbose_name='Order', default=1)
prodQuery = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='Product', default=1)
poQty = models.PositiveIntegerField(default=0, verbose_name='Quantity')
class Meta:
constraints = [
models.UniqueConstraint(fields=('poOrder', 'prodQuery'), name='once_per_product_order')
]
forms.py
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['orderOpen', 'orderTable', 'menuQuery',]
def __init__(self, *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['menuQuery'].queryset = Menu.objects.filter(menuActive=True)
class ProductOrderForm(ModelForm):
filtered_products = None
class Meta:
model = ProductOrder
fields = ['prodQuery', 'poQty',]
widgets = {'prodQuery': TextInput}
def __init__(self, *args, **kwargs):
super(ProductOrderForm, self).__init__(*args, **kwargs)
self.filtered_products = Product.objects.filter(menu__prodQuery = self.instance.prodQuery)
self.fields['prodQuery'].queryset = self.filtered_products
def save(self, commit=True):
print('*function save*')
data = super(ProductOrderForm, self).save(commit=False)
if data.poQty > 0 and commit:
data.save()
return data
views.py
def create_order(request):
form = OrderForm(request.POST or None, request.FILES or None)
filtered_products = ProductOrderForm()
ProductOrderFormset = inlineformset_factory(Order, Order.prodQuery.through, form = ProductOrderForm,
extra = len(filtered_products.filtered_products),
can_delete = False)
if request.POST and form.is_valid():
order = form.save(commit=False)
formset = ProductOrderFormset(request.POST, instance=order)
if formset.is_valid():
try:
order.save()
formset.save()
return redirect('/orders')
except:
pass
else:
formset = ProductOrderFormset(request.POST or None, instance=Order(),
initial=[{'prodQuery': prod.id} for prod in filtered_products.filtered_products],)
context = {
'form': form,
'formset': formset,
}
return render(request,'create_order.html', context)