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…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer