Adds “CategoryForm” to forms.py. It’s about to replace the existing ProductItem form

This commit is contained in:
Christopher Neugebauer 2016-03-04 18:01:16 -08:00
parent 68e7e4e594
commit 745f6db444
3 changed files with 80 additions and 33 deletions

View file

@ -3,11 +3,46 @@ import models as rego
from django import forms
class ProductItemForm(forms.Form):
product = forms.ModelChoiceField(queryset=None, empty_label=None)
quantity = forms.IntegerField()
def CategoryForm(category):
def __init__(self, category, *a, **k):
super(ProductItemForm, self).__init__(*a, **k)
products = rego.Product.objects.filter(category=category)
self.fields['product'].queryset = products
PREFIX = "product_"
def field_name(product):
return PREFIX + ("%d" % product.id)
class _CategoryForm(forms.Form):
@staticmethod
def initial_data(product_quantities):
''' Prepares initial data for an instance of this form.
product_quantities is a sequence of (product,quantity) tuples '''
initial = {}
for product, quantity in product_quantities:
initial[field_name(product)] = quantity
return initial
def product_quantities(self):
''' Yields a sequence of (product, quantity) tuples from the
cleaned form data. '''
for name, value in self.cleaned_data.items():
if name.startswith(PREFIX):
product_id = int(name[len(PREFIX):])
yield (product_id, value, name)
def disable_product(self, product):
''' Removes a given product from this form. '''
del self.fields[field_name(product)]
products = rego.Product.objects.filter(category=category).order_by("order")
for product in products:
help_text = "$%d -- %s" % (product.price, product.description)
field = forms.IntegerField(
label=product.name,
help_text=help_text,
)
_CategoryForm.base_fields[field_name(product)] = field
return _CategoryForm

View file

@ -9,12 +9,14 @@
<form method="post" action="">
{% csrf_token %}
<table>
{{ formset }}
{{ form }}
</table>
<input type="submit">
</form>
{% endblock %}

View file

@ -6,11 +6,10 @@ from registrasion.controllers.product import ProductController
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError
from django.db import transaction
from django.forms import formset_factory
from django.shortcuts import redirect
from django.shortcuts import render
from functools import partial, wraps
@login_required
@ -20,50 +19,61 @@ def product_category(request, category_id):
category_id = int(category_id) # Routing is [0-9]+
category = rego.Category.objects.get(pk=category_id)
ProductItemFormForCategory = (
wraps(forms.ProductItemForm)
(partial(forms.ProductItemForm, category=category)))
ProductItemFormSet = formset_factory(ProductItemFormForCategory, extra=0)
CategoryForm = forms.CategoryForm(category)
products = rego.Product.objects.filter(category=category)
products = products.order_by("order")
if request.method == "POST":
formset = ProductItemFormSet(request.POST, request.FILES)
if formset.is_valid():
cat_form = CategoryForm(request.POST, request.FILES)
if cat_form.is_valid():
current_cart = CartController.for_user(request.user)
with transaction.atomic():
for form in formset.forms:
data = form.cleaned_data
# TODO set form error instead of failing completely
current_cart.set_quantity(
data["product"], data["quantity"], batched=True)
current_cart.end_batch()
try:
with transaction.atomic():
for product_id, quantity, field_name \
in cat_form.product_quantities():
product = rego.Product.objects.get(pk=product_id)
try:
current_cart.set_quantity(
product, quantity, batched=True)
except ValidationError as ve:
cat_form.add_error(field_name, ve)
if cat_form.errors:
raise ValidationError("Cannot add that stuff")
current_cart.end_batch()
except ValidationError as ve:
pass
else:
# Create initial data for each of products in category
initial = []
products = rego.Product.objects.filter(category=category)
items = rego.ProductItem.objects.filter(product__category=category)
products = products.order_by("order")
quantities = []
for product in products:
# Only add items that are enabled.
prod = ProductController(product)
if not prod.can_add_with_enabling_conditions(request.user, 0):
continue
try:
quantity = items.get(product=product).quantity
except ObjectDoesNotExist:
quantity = 0
data = {"product": product, "quantity": quantity}
initial.append(data)
quantities.append((product, quantity))
formset = ProductItemFormSet(initial=initial)
initial = CategoryForm.initial_data(quantities)
cat_form = CategoryForm(initial=initial)
for product in products:
# Remove fields that do not have an enabling condition.
prod = ProductController(product)
if not prod.can_add_with_enabling_conditions(request.user, 0):
cat_form.disable_product(product)
data = {
"category": category,
"formset": formset,
"form": cat_form,
}
return render(request, "product_category.html", data)
@login_required
def checkout(request):
''' Runs checkout for the current cart of items, ideally generating an