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')
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With