Мне удалось частично отойти от поведения, к которому я стремлюсь. У меня есть два вопроса:
- Мой подход кажется довольно запутанным, и мне интересно, есть ли лучший способ
- В текущем подходе мне удается получить основы c Однако я ищу поведение, если форма недействительна. Я теряю начальные значения в inlineformset приема, когда форма повторно отображается
У меня есть четыре модели, которые связаны друг с другом в процессе покупки :
- Order
- OrderLine
- Reception
- ReceptionLine
Заказ на покупку и его дочерний заказ на покупку линии генерируются с помощью inlineformset - это работает просто отлично. Когда дело доходит до записи приема, я пытаюсь получить набор inlineform приема, чтобы сгенерировать начальные строки приема на основе того, что было введено в качестве строк заказа на покупку. Статус приема записывается в строке заказа на покупку с помощью сигналов.
models.py
class Order(models.Model):
requestor = models.CharField(max_length=10)
class OrderLine(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
item = models.CharField(max_length=30)
quantity_ordered = models.PositiveIntegerField()
quantity_received = models.PositiveIntegerField(blank=True, default=0)
quantity_remaining = models.PositiveIntegerField(blank=True, default=0)
class Reception(models.Model):
order = models.ForeignKey('purchase.Order', on_delete=models.SET_NULL, null=True)
receiver = models.CharField(max_length=10)
class ReceptionLine(models.Model):
reception = models.ForeignKey(Reception, on_delete=models.CASCADE)
order_line = models.ForeignKey('purchase.OrderLine', on_delete=models.SET_NULL, null=True)
quantity = models.PositiveIntegerField()
views.py
class Create(generic.CreateView):
model = receive_models.Reception
form_class = receive_forms.ReceptionForm
template_name = 'generic/edit.html'
def get_initial(self):
order = get_object_or_404(purchase_models.Order, pk=self.kwargs['pk'])
initial = super(Create, self).get_initial()
initial['order'] = order
return initial
def get(self, request, *args, **kwargs):
order = get_object_or_404(purchase_models.Order, pk=self.kwargs['pk'])
order_line = order.orderline_set.values(
order_line=F('id'),
item_name=F('item'),
qty_ordered=F('quantity_ordered'),
qty_received=F('quantity_received'),
qty_remaining=F('quantity_remaining')
)
order_line_count = order_line.count()
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
formset = receive_forms.ReceptionLineFormSet(queryset=purchase_models.OrderLine.objects.none(), initial=order_line)
return self.render_to_response(self.get_context_data(form=form, formset=formset))
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
formset = receive_forms.ReceptionLineFormSet(self.request.POST, instance=form.instance)
if form.is_valid() and formset.is_valid():
return self.is_valid(form, formset)
else:
return self.is_invalid(form, formset)
def is_valid(self, form, formset):
self.object = form.save(commit=False)
self.object.created_by = self.request.user
with transaction.atomic():
self.object.save()
formset.save()
return super().form_valid(form)
def is_invalid(self, form, formset):
return self.render_to_response(self.get_context_data(form=form, formset=formset))
forms.py
class ReceptionForm(forms.ModelForm):
class Meta:
model = models.Reception
fields = ['receiver', 'order']
def __init__(self, *args, **kwargs):
super(ReceptionForm, self).__init__(*args, **kwargs)
self.fields['order'].disabled = True
self.helper = FormHelper()
self.helper.form_tag = False
class ReceptionLineForm(forms.ModelForm):
item_name = forms.CharField(disabled=True, required=False)
qty_ordered = forms.IntegerField(disabled=True, required=False)
qty_received = forms.IntegerField(disabled=True, required=False)
qty_remaining = forms.IntegerField(disabled=True, required=False)
class Meta:
model = models.ReceptionLine
fields = ['order_line', 'item_name', 'qty_ordered', 'qty_received', 'qty_remaining', 'quantity']
widgets = {'order_line': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super(ReceptionLineForm, self).__init__(*args, **kwargs)
self.fields['order_line'].disabled = False
self.fields['order_line'].required = False
self.helper = FormHelper()
self.helper.template = 'bootstrap4/layout/table_inline_formset.html'
self.helper.form_tag = False
ReceptionLineFormSet = forms.inlineformset_factory(
parent_model=models.Reception,
model=models.ReceptionLine,
form=ReceptionLineForm,
extra=2,
min_num=1
)
signal.py
@receiver(pre_save, sender = ReceptionLine)
def update_orderline(sender, instance, **kwargs):
orderline = OrderLine.objects.get(id=instance.order_line.id)
orderline.quantity_received += instance.quantity
orderline.quantity_remaining = orderline.quantity_ordered - orderline.quantity_received
orderline.save()