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
|
from django import forms
|
||||||
|
|
||||||
|
|
||||||
class ProductItemForm(forms.Form):
|
def CategoryForm(category):
|
||||||
product = forms.ModelChoiceField(queryset=None, empty_label=None)
|
|
||||||
quantity = forms.IntegerField()
|
|
||||||
|
|
||||||
def __init__(self, category, *a, **k):
|
PREFIX = "product_"
|
||||||
super(ProductItemForm, self).__init__(*a, **k)
|
|
||||||
products = rego.Product.objects.filter(category=category)
|
def field_name(product):
|
||||||
self.fields['product'].queryset = products
|
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="">
|
<form method="post" action="">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ formset }}
|
{{ form }}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<input type="submit">
|
<input type="submit">
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -6,11 +6,10 @@ from registrasion.controllers.product import ProductController
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.forms import formset_factory
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from functools import partial, wraps
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -20,50 +19,61 @@ def product_category(request, category_id):
|
||||||
category_id = int(category_id) # Routing is [0-9]+
|
category_id = int(category_id) # Routing is [0-9]+
|
||||||
category = rego.Category.objects.get(pk=category_id)
|
category = rego.Category.objects.get(pk=category_id)
|
||||||
|
|
||||||
ProductItemFormForCategory = (
|
CategoryForm = forms.CategoryForm(category)
|
||||||
wraps(forms.ProductItemForm)
|
|
||||||
(partial(forms.ProductItemForm, category=category)))
|
products = rego.Product.objects.filter(category=category)
|
||||||
ProductItemFormSet = formset_factory(ProductItemFormForCategory, extra=0)
|
products = products.order_by("order")
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
formset = ProductItemFormSet(request.POST, request.FILES)
|
cat_form = CategoryForm(request.POST, request.FILES)
|
||||||
if formset.is_valid():
|
if cat_form.is_valid():
|
||||||
current_cart = CartController.for_user(request.user)
|
current_cart = CartController.for_user(request.user)
|
||||||
with transaction.atomic():
|
try:
|
||||||
for form in formset.forms:
|
with transaction.atomic():
|
||||||
data = form.cleaned_data
|
for product_id, quantity, field_name \
|
||||||
# TODO set form error instead of failing completely
|
in cat_form.product_quantities():
|
||||||
current_cart.set_quantity(
|
product = rego.Product.objects.get(pk=product_id)
|
||||||
data["product"], data["quantity"], batched=True)
|
try:
|
||||||
current_cart.end_batch()
|
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:
|
else:
|
||||||
# Create initial data for each of products in category
|
# 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)
|
items = rego.ProductItem.objects.filter(product__category=category)
|
||||||
products = products.order_by("order")
|
quantities = []
|
||||||
for product in products:
|
for product in products:
|
||||||
# Only add items that are enabled.
|
# Only add items that are enabled.
|
||||||
prod = ProductController(product)
|
prod = ProductController(product)
|
||||||
if not prod.can_add_with_enabling_conditions(request.user, 0):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
quantity = items.get(product=product).quantity
|
quantity = items.get(product=product).quantity
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
quantity = 0
|
quantity = 0
|
||||||
data = {"product": product, "quantity": quantity}
|
quantities.append((product, quantity))
|
||||||
initial.append(data)
|
|
||||||
|
|
||||||
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 = {
|
data = {
|
||||||
"category": category,
|
"category": category,
|
||||||
"formset": formset,
|
"form": cat_form,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, "product_category.html", data)
|
return render(request, "product_category.html", data)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def checkout(request):
|
def checkout(request):
|
||||||
''' Runs checkout for the current cart of items, ideally generating an
|
''' Runs checkout for the current cart of items, ideally generating an
|
||||||
|
|
Loading…
Reference in a new issue