Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django dynamic form, formsets with HTML array

Im trying to create a dynamic form that uses a models relationship to generate the formset.

Here is a brief overview of the application. I have a customer table (joined to django admin user table), products table, order table and some join tables. The customer_product table contains a pre built order form that can be edited. I use some join table to create new order_instances that can be referenced from the order table for historical data.

` Customer has one to one relationship with user table

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


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

` Customer has and belongs to many products

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

' Customer has and belongs to many products. Customer has many orders

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

I don't know how to use formsets in this case, that will let be build dynamic form and save to a customer_product_order table and order table. Currently i have the form outputting but it's checking the customer_product table the second time rather than letting the forms.py oncstruct it. Also couldnt construct the html array in forms.py page.

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)

template

{% 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

With regards to comments about models. I have detailed the relationships above as best as I can. The design and requirements of the app are as follow. Each customer hasone user. A customer order sheet is prebuilt by administrators and store in the customer_product table. Customer hasand belongstomany products and customer hasmanyorders. When an order is placed by the customer, a new order record is added, and the customer_products_order join table is populated, along with quantities of each product.

The customer_product table is pre-populated by administrators. The customer_product_order (join) and order table is populated by customers.

I was using the following join to grab customer information from the order model. I couldn't find any other way to recursively join the customer table from the order model. I may be wrong. Even though this is beyond this question, I really appreciate any comments on my code!

models.ManyToManyField('CustomerProduct', through='CustomerProductOrder')
like image 677
madphp Avatar asked Aug 14 '15 20:08

madphp


1 Answers

From the discussion we started in the comments and your updated answer, I am unsure about the purpose of you customer_product table ? I will update my answer if I finally get it.

(It would actually seem to me that your customer_id field in customer_product model is redundant with the customer_id field in customer_product_order, making the table customer_product not actually usefull.)


To model a product ordering system, you could perhaps move the customer_id at the order level (from what I understand of your requirements, there a Customer has many orders, but and order has a single customer, which the current design fails to implement), giving you:

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

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

If this model could suit your need, can you clarify what is the question you are facing ?


EDIT: I think the data modeling is slightly off, and it is not conveying the right message about what you are trying to achieve (making it complicated to help ;). In particular:

Customer hasand belongstomany products

Seems it could be a misconception: why would a Customer belong to a product ?
It seems more natural that the Customer would have a many-to-one relationship with Order instances. And a Order would have a many-to-one relationship with Products, potentially joined through an external table containing the quantity field (i.e., your CustomerProductOrder table).

That would give you this updated and simplified model:



    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


Could you please explain why this more trivial design would not be fit for your purpose ? (Hoping that it will allow us to better understand your requirements)

like image 55
Ad N Avatar answered Oct 19 '22 04:10

Ad N