Adds “CategoryForm” to forms.py. It’s about to replace the existing ProductItem form
This commit is contained in:
parent
68e7e4e594
commit
745f6db444
3 changed files with 80 additions and 33 deletions
|
@ -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
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
|
||||
<table>
|
||||
{{ formset }}
|
||||
{{ form }}
|
||||
</table>
|
||||
|
||||
<input type="submit">
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue