Changeset - 745f6db444fa
[Not reviewed]
0 3 0
Christopher Neugebauer - 8 years ago 2016-03-23 04:04:51
chrisjrn@gmail.com
Adds “CategoryForm” to forms.py. It’s about to replace the existing ProductItem form
3 files changed with 81 insertions and 34 deletions:
0 comments (0 inline, 0 general)
registrasion/forms.py
Show inline comments
...
 
@@ -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 __init__(self, category, *a, **k):
 
        super(ProductItemForm, self).__init__(*a, **k)
 
        products = rego.Product.objects.filter(category=category)
 
        self.fields['product'].queryset = products
 
def CategoryForm(category):
 

	
 
    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
registrasion/templates/product_category.html
Show inline comments
...
 
@@ -9,12 +9,14 @@
 

	
 
  <form method="post" action="">
 
    {% csrf_token %}
 

	
 
    <table>
 
        {{ formset }}
 
        {{ form }}
 
    </table>
 

	
 
    <input type="submit">
 

	
 
  </form>
 

	
 

	
 
{% endblock %}
registrasion/views.py
Show inline comments
...
 
@@ -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))
 

	
 
        initial = CategoryForm.initial_data(quantities)
 
        cat_form = CategoryForm(initial=initial)
 

	
 
        formset = ProductItemFormSet(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
0 comments (0 inline, 0 general)