Задать вопрос
Beerenfeld
@Beerenfeld

Почему inlineformset не сохраняет данные?

Есть вот такие модели
class Order(models.Model):
    number = models.CharField('Код заказа', max_length=12)
    date = models.DateField('Дата создания', default=datetime.now)
    deadline = models.DateField('Срок изготовления')
    worth = models.DecimalField('ИТОГО', max_digits=10, decimal_places=2)
    prepayment = models.DecimalField('Предоплата', max_digits=10, decimal_places=2)
    check_img = models.ImageField(upload_to='orders/%Y/%m/%d', blank=True)
    city = models.ForeignKey(City, on_delete=PROTECT, default=1)
    saloon = models.ForeignKey(Saloon, on_delete=PROTECT)
    user = models.ForeignKey(User, on_delete=PROTECT, default=1)
    client = models.ForeignKey(Client, on_delete=PROTECT)
    furniture = models.ManyToManyField(Furniture, through='OrderItem')

    class Meta:
        db_table = 'order'
        verbose_name = "Заказ"
        verbose_name_plural = "Заказы"

    def __str__(self):
        return self.worth
    

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=PROTECT)
    furniture = models.ForeignKey(Furniture, on_delete=PROTECT)
    seat_len = models.PositiveIntegerField('Длина сиденья')
    seat_deep = models.PositiveIntegerField('Глубина сиденья')
    back_len = models.PositiveIntegerField('Длина спинки')
    back_deep = models.PositiveIntegerField('Глубина спинки')
    otto_len = models.PositiveIntegerField('Длина оттоманки')
    otto_deep = models.PositiveIntegerField('Глубина оттоманки')
    quantity = PositiveIntegerField()
    tex1 = models.ForeignKey(Tex, default=1, on_delete=PROTECT, related_name='tex1')
    tex2 = models.ForeignKey(Tex, default=1, on_delete=PROTECT, related_name='tex2')

    def __str__(self):
        return f'Id: {self.pk }, {self.furniture} for OrderId: {self.order.pk}'

    class Meta:
        db_table = 'order_item'
        verbose_name = "Позиция заказа"
        verbose_name_plural = "Позиции заказа"

Вот такие формы

class OrderItemForm(ModelForm):
    furniture = ModelChoiceField(queryset=Furniture.objects.all(), empty_label='Модель не выбрана', label='Модель')
    tex1 = ModelChoiceField(queryset=Tex.objects.all(), empty_label='Ткань не выбрана', label='Основная ткань')
    tex2 = ModelChoiceField(queryset=Tex.objects.all(), empty_label='Ткань не выбрана', label='Ткань компаньон')

    class Meta:
        model = OrderItem
        fields = ['furniture', 'tex1', 'tex2', 'seat_len', 'seat_deep', 'back_len', 'back_deep', 'otto_len', 'otto_deep', 'quantity']

        widgets = {
            'furniture': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Модель'
            }),
            'tex1': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Основная ткань'
            }),
            'tex2': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Ткань компаньон'
            }),
            'seat_len': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение длины сиденья'
            }),
            'seat_deep': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение глубины сиденья'
            }),
            'back_len': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение длины спинки'
            }),
            'back_deep': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение ширины спинки'
            }),
            'otto_len': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение длины оттоманки'
            }),
            'otto_deep': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изменение глубины оттоманки'
            }),
            'quantity': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Количество в заказе'
            })
        }


OrderItemInlineFormset = inlineformset_factory(Order, OrderItem, form=OrderItemForm, extra=5)


class OrderForm(ModelForm):
    client = ModelChoiceField(queryset=Client.objects.all(), empty_label='Клиент не выбран', label='Клиент')
    saloon = ModelChoiceField(queryset=Saloon.objects.all(), empty_label='Салон не выбран', label='Салон')

    class Meta:
        model = Order
        fields = ['number', 'deadline', 'client', 'saloon', 'worth', 'prepayment']

        widgets = {
            'number': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Номер заказа'
            }),
            'deadline': TextInput(attrs={
                'class': 'form-control',
                'type': 'date',
                'placeholder': 'Срок'
            }),
            'client': TextInput(attrs={
                'class': 'form-control',
                'type': 'input-group-text',
                'placeholder': 'Клиент'
            }),
            'saloon': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Салон'
            }),
            'worth': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Общая сумма заказа'
            }),
            'prepayment': TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Предоплата'
            })
        }


Вот такое представление для создания заказа:
class orderCreateView(CreateView):
    form_class = OrderForm
    success_url = '/orders/orders/'
    template_name = 'orders/orders/orderCreate.html'

    def get_context_data(self, **kwargs):
        context = super(orderCreateView, self).get_context_data(**kwargs)
        context['order_item_formset'] = OrderItemInlineFormset()
        return context

    def post(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        order_item_formset = OrderItemInlineFormset(self.request.POST)

        if form.is_valid() and order_item_formset.is_valid():
            return self.form_valid(form, order_item_formset)
        else:
            return self.form_invalid(form, order_item_formset)

    def form_valid(self, form, order_item_formset):
        self.object = form.save(commit=False)
        self.object.save()
        # saving OrderItems Instances
        order_metas = order_item_formset.save(commit=False)
        for meta in order_metas:
            meta.order = self.object
            meta.save()
        return redirect(reverse("orders"))

    def form_invalid(self, form, order_item_formset):
        return self.render_to_response(
            self.get_context_data(form=form,
                                  order_item_formset=order_item_formset
                                  )
        )


Ну и шаблон
{% extends 'orders/layout.html' %}

{% block title %}Новый заказ{% endblock %}
{% block titleH1 %}Новый заказ{% endblock %}

{% block content %}
<form method="post">
        {% csrf_token %}
        <h1>Создание заказа</h1>
        {{ form.non_form_errors }}
        {{ form.as_p }}
        <h5 class="text-info">Добавить позиции заказа</h5>
        {{ order_item_formset.non_form_errors }}
        {{ order_item_formset.management_form }}
        <p>
        <table border="1" bgcolor="white">
            <thead bgcolor="#320C8F">
                <th width="70">Модель</th>
                <th width="60">Осн.ткань</th>
                <th width="200">Компаньон</th>
                <th width="30%">Кол-во</th>
                <th width="100">Действие</th>
            </thead>
                {% for form in order_item_formset %}
                <tr>
                    <td>{{ form.furniture }}</td>
                    <td>{{ form.tex1 }}</td>
                    <td>{{ form.tex2 }}</td>
                    <td>{{ form.quantity }}</td>
                    <td>{% if order_item_formset.can_delete %}
                        {{ form.DELETE }} {{ form.DELETE.label }}
                    {% endif %}
                    </td>
                </tr>
                {% endfor %}
        </table>
        </p>
    <button type="submit" class="btn btn-warning">Добавить</button>
    </form>
{% endblock %}


По нажатию кнопки "Добавить" поля формы с содержимым заказа очищаются, переход на страницу со списком заказов не осуществляется. Поля с номером заказа, данными заказчика и проч. остаются заполненными. А нужно, соответственно, сохранить заказ со всеми позициями.
Что я делаю не так, где ошибка?
  • Вопрос задан
  • 29 просмотров
Подписаться 1 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы