Динамическая форма Django, формы с массивом HTML

Я пытаюсь создать динамическую форму, которая использует отношения моделей для создания набора форм.

Вот краткий обзор приложения. У меня есть таблица клиентов (объединена с django admin user table), таблица продуктов, таблица заказов и некоторые таблицы соединений. Таблица customer_product содержит предварительно созданную форму заказа, которую можно редактировать. Я использую некоторую таблицу соединений для создания новых параметров order_instances, на которые можно ссылаться из таблицы заказов для исторических данных.

Клиент имеет отношения один к одному с пользовательской таблицей

customer table
--------------
id


product table
-------------
id | product_id

`Клиент имеет и принадлежит ко многим продуктам

customer_product (pre-built order templates)
----------------
id | customer_id | product_id

Клиент имеет и принадлежит ко многим продуктам. Клиент имеет много заказов

customer_product_order (customer initiated order)
----------------------
id | customer_id | product_id | order_id | quantity

order (main order table. each record contains meta data for that order)
-------
id | invoice_number | delivery_date

Я не знаю, как использовать формы в этом случае, что позволит создать динамическую форму и сохранить в таблице customer_product_order и таблице заказов. В настоящее время у меня есть форма вывода, но она проверяет таблицу customer_product во второй раз, а не позволяет form.py настраивать ее. Также не удалось создать массив html на странице forms.py.

models.py

from django.conf import settings
from django.db import models
from datetime import datetime
import pprint

class Customer(models.Model):
    customer = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': "customers"})
    customer_product = models.ManyToManyField('Product', through='CustomerProduct')
    company_name = models.CharField(max_length=255)
    address1 = models.CharField(max_length=255)
    address2 = models.CharField(max_length=255)
    city = models.CharField(max_length=255)
    state = models.CharField(max_length=255)
    zip_code = models.CharField(max_length=255)
    created_date = models.DateTimeField('date created')
    def __unicode__(self):
        return self.company_name

class CustomerProduct(models.Model):
    customer = models.ForeignKey('Customer')
    product = models.ForeignKey('Product')
    def __unicode__(self):
        return self.customer.company_name

class Product(models.Model):
    item = models.CharField(max_length=255)
    description = models.CharField(max_length=255)
    def __unicode__(self):
        return self.description

class Order(models.Model):
    customer_product_order = models.ManyToManyField('CustomerProduct', through='CustomerProductOrder')
    purchase_order_number = models.CharField(max_length=10)
    person_placing_order = models.CharField(max_length=255)

class CustomerProductOrder(models.Model):
    order = models.ForeignKey('Order')
    customer_product = models.ForeignKey('CustomerProduct')
    quantity = models.IntegerField(default=0)
    instructions = models.CharField(max_length=2000)
    order_correct = models.BooleanField()
    def __unicode__(self):
        return self.customer_product.customer.company_name

    class Meta:
        verbose_name = "Customer Order"

forms.py

from django import forms

from .models import CustomerProduct

class OrderForm(forms.Form):
    def __init__(self, *args, **kwargs):
        products = CustomerProduct.objects.filter(customer_id=1)

        super(OrderForm, self).__init__(*args, **kwargs)
        counter = 1
        for q in products:
            self.fields['product[quantity][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            self.fields['product[item][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            self.fields['product[description][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            counter += 1

    purchase_order_number = forms.CharField(required=True)
    person_placing_order =  forms.CharField(required=True)
    delivery_date_request = forms.DateField(required=True,widget=forms.DateInput(attrs={'class':'datepicker'}))
    instructions = forms.CharField(required=False,widget=forms.Textarea(attrs={'rows': 5, 'cols': 100, 'class': 'form-control'}))
    confirm_order = forms.BooleanField(required=True)

views.py

from django import forms

from .models import CustomerProduct

class OrderForm(forms.Form):
    def __init__(self, *args, **kwargs):
        products = CustomerProduct.objects.filter(customer_id=1)

        super(OrderForm, self).__init__(*args, **kwargs)
        counter = 1
        for q in products:
            self.fields['product[quantity][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            self.fields['product[item][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            self.fields['product[description][' + str(q.id) + ']' + str(counter)] = forms.CharField(required=False)
            counter += 1

    purchase_order_number = forms.CharField(required=True)
    person_placing_order =  forms.CharField(required=True)
    delivery_date_request = forms.DateField(required=True,widget=forms.DateInput(attrs={'class':'datepicker'}))
    instructions = forms.CharField(required=False,widget=forms.Textarea(attrs={'rows': 5, 'cols': 100, 'class': 'form-control'}))
    confirm_order = forms.BooleanField(required=True)

шаблон

{% extends "base.html" %}

{% block orderform %}
    {% if form.errors %}
        <p style="color: red;">
            Please correct the error{{ form.errors|pluralize }} below.
        </p>
    {% endif %}

    <form action="/onlineordering/" method="POST">

        <form class="form-inline">

            {% csrf_token %}

            <div class="row">
                <div class="col-md-6">

                    <div class="form-group">
                        <div class="row">
                            <div class="col-md-5"><label for="exampleInputName2">Date</label></div>
                            <div class="col-md-7">{{ datenow }}</div>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="row">
                            <div class="col-md-5"><label for="exampleInputName2">Customer ID:</label></div>
                            <div class="col-md-7">{{ username }}</div>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="row">
                            <div class="col-md-5"><label for="exampleInputName2">Address</label></div>
                            <div class="col-md-7">
                                1 Main Street<br />
                                Town<br />
                                State<br />
                            </div>
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="row">
                            <div class="col-md-5"><label for="exampleInputName2">Purchase Order Number</label></div>
                            <div class="col-md-7">{{ form.purchase_order_number }}</div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="row">
                            <div class="col-md-5"><label for="exampleInputEmail2">Person Placing Order</label></div>
                            <div class="col-md-7">{{ form.person_placing_order }}</div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="form-group">
                            <div class="row">
                                <div class="col-md-5"><label for="exampleInputEmail2">Requested Delivery Date</label></div>
                                <div class="col-md-7">{{ form.delivery_date_request }}</div>
                            </div>
                        </div>
                    </div>

                </div>
                <div class="col-md-6">
                    <p class="text-right">

                    </p>
                </div>
            </div>

            <table class="table table-bordered online-ordering-table">
                <tr>
                    <th width="10%">Quantity</th>
                    <th width="20%">Item</th>
                    <th width="70%">Description</th>
                </tr>

                {% for product in products %}

                <tr>
                    <td><input name="product_quantity"  /></td>
                    <td>{{ product.product.item }}</td>
                    <td>{{ product.product.description }}</td>
                </tr>

                {% endfor %}

            </table>

            <div class="form-group">
                <label for="exampleInputEmail2">Special Instructions / Comments</label>
                {{ form.instructions }}
            </div>

            <div class="form-group">
                <div class="checkbox">
                    <label>
                        {{ form.confirm_order }} I concede the order above is correct and authorize Company to fulfill this order
                    </label>
                </div>
            </div>

            <input class="btn" type="submit" value="Submit">
        </form>

    </form>
{% endblock %}

UPDATE

Что касается комментариев о моделях. Я подробно описал отношения выше, чем могу. Дизайн и требования к приложению следующие. Каждому пользователю hasone. Лист заказа клиента предварительно создан администраторами и хранится в таблице customer_product. Клиент имеет и принадлежит продукции и hasmanyorders. Когда заказ размещается клиентом, добавляется новая запись заказа и заполняется таблица соединения customer_products_order вместе с количеством каждого продукта.

Таблица customer_product предварительно заполняется администраторами. Таблица customer_product_order (join) и таблица заказов заполняется клиентами.

Я использовал следующее соединение, чтобы получить информацию о клиентах из модели заказа. Я не мог найти другого способа рекурсивно присоединиться к таблице клиентов из модели заказа. Возможно, я ошибаюсь. Несмотря на то, что это выходит за рамки этого вопроса, я действительно ценю любые комментарии к моему коду!

models.ManyToManyField('CustomerProduct', through='CustomerProductOrder')

Ответ 1

Из обсуждения, которое мы начали в комментариях и вашем обновленном ответе, я не уверен в цели вашей таблицы customer_product? Я обновлю свой ответ, если наконец получу его.

(На самом деле мне кажется, что ваше поле customer_id в модели customer_product избыточно с полем customer_id в customer_product_order, что делает таблицу customer_product фактически не полезной.)


Чтобы смоделировать систему заказа продукта, вы могли бы переместить customer_id на уровне order (из того, что я понимаю из ваших требований, там Customer имеет много заказов, но и порядок имеет одиночный клиент, который текущий проект не реализует), предоставляя вам:

product_order
----------------------
id | product_id(ForeignKey) | order_id(ForeignKey) | quantity

order
-------
id | customer_id(ForeignKey) | invoice_number | delivery_date

Если эта модель может удовлетворить ваши потребности, можете ли вы уточнить, к какому вопросу вы столкнулись?


РЕДАКТИРОВАТЬ: Я думаю, что моделирование данных немного отключено, и оно не передает правильное сообщение о том, чего вы пытаетесь достичь (что затрудняет его помощь;). В частности:

Клиент имеет и владеет некоторыми продуктами

Кажется, это может быть неправильное представление: почему клиент принадлежит к продукту?
Кажется более естественным, что Customer будет иметь отношение "много к одному с экземплярами order. А order будет иметь отношение one2 > с Products, потенциально связанное через внешнюю таблицу, содержащую поле quantity (т.е. Таблицу CustomerProductOrder).

Это даст вам эту обновленную и упрощенную модель:



    customer table
    --------------
    id | ...


    product table
    -------------
    id | description | ...


    order
    -------
    id | customer_id(ForeignKey) | person_placing_order | invoice_number | delivery_date


    order_content (~= customer_product_order)
    ----------------------
    id | order_id(ForeignKey)  | customer_id | product_id(ForeignKey) | product_quantity


Не могли бы вы объяснить, почему этот более простой дизайн не подходит для вашей цели? (Надеясь, что это позволит нам лучше понять ваши требования)