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')
Model? In particular, your design makes it seem you want to be able to have different customers for a single order, is that intentional ?Orderhas manyCustomerProducts. Since eachCustomerProducthas aCustomer, it results that a singleOrdercan have several differentCustomers. Also, because the ManyToMany relation is bidirectional, the sameCustomerProductcan be part of differentOrders. All those choices are going against the intuitive design (example, violating the fact that there is a singleCustomerfor any givenOrder). I think you should give more details about the intention behind each of yourModelclasses, and your design decisions, in order to receive some answers.