def __init__(self, request, step, data=None, initial=None, checkout_errors=None): """ Handle setting shipping field values to the same as billing field values in case Javascript is disabled, hiding fields for current step and hiding discount_code field if there are currently no active discount codes. """ # Copy billing fields to shipping fields if "same" checked. if (step == CHECKOUT_STEP_FIRST and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when moving # backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is required to # allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(data=data, initial=initial) self._request = request self._checkout_errors = checkout_errors # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if step == CHECKOUT_STEP_FIRST: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: f.startswith("card_") elif step == CHECKOUT_STEP_PAYMENT: # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and \ step == CHECKOUT_STEP_LAST: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Hide Discount Code field if no codes are active. if DiscountCode.objects.active().count() == 0: self.fields["discount_code"].widget = forms.HiddenInput() # Set the choices for the cc expiry year relative to the current year. year = datetime.now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices
def __init__(self, request, step, data=None, initial=None, errors=None): OrderForm.__init__(self, request, step, data, initial, errors) is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT # Get list of country names countries = make_choices(get_country_names_list()) if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Change country widgets to a Select widget self.fields["billing_detail_country"].widget = forms.Select(choices=countries) self.fields["billing_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY self.fields["shipping_detail_country"].widget = forms.Select(choices=countries) self.fields["shipping_detail_country"].initial= settings.SHOP_DEFAULT_COUNTRY if is_payment_step: # Make card number and cvv fields use the data encrypted widget self.fields["card_number"].widget = DataEncryptedTextInput() self.fields["card_ccv"].widget = DataEncryptedPasswordInput() else: # Change country widgets to a Select widget self.fields["billing_detail_country"].widget = forms.Select(choices=countries) self.fields["billing_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY self.fields["shipping_detail_country"].widget = forms.Select(choices=countries) self.fields["shipping_detail_country"].initial= settings.SHOP_DEFAULT_COUNTRY if settings.SHOP_PAYMENT_STEP_ENABLED: # Make card number and cvv fields use the data encrypted widget self.fields["card_number"].widget = DataEncryptedTextInput() self.fields["card_ccv"].widget = DataEncryptedPasswordInput()
def __init__(self, *args, **kwargs): """ Set the choices for each of the fields for product options, hiding them if no choices exist. """ super(ProductAdminForm, self).__init__(*args, **kwargs) for field, options in ProductOption.objects.as_fields().items(): self.fields[field].choices = make_choices(options)
def __init__(self, request, step, data=None, initial=None, errors=None): """ Handle setting shipping field values to the same as billing field values in case JavaScript is disabled, hiding fields for the current step. """ # Copy billing fields to shipping fields if "same" checked. first = step == checkout.CHECKOUT_STEP_FIRST last = step == checkout.CHECKOUT_STEP_LAST if (first and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when # moving backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is # required to allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors settings.use_editable() # Hide Discount Code field if no codes are active. if (DiscountCode.objects.active().count() == 0 or not settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if first: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: f.startswith("card_") elif step == checkout.CHECKOUT_STEP_PAYMENT: # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and last: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set the choices for the cc expiry year relative to the current year. year = datetime.now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices
class StripeOrderForm(OrderForm): """ Derived order form that implements nameless cc and stripeToken inputs. Derived form class for Order model. """ # "required" is a core Field argument, and is used by the Field.clean method. # if required=False, then clean does not raise a ValdationError on empty values. # clean raises this error or returns a cleaned value card_number = forms.CharField( label=_("Card number"), required=False, widget=NamelessTextInput(attrs={"data-stripe": "number"})) card_expiry_month = forms.ChoiceField( label=_("Card expiry month"), initial="%02d" % date.today().month, choices=make_choices(["%02d" % i for i in range(1, 13)]), required=False, widget=NamelessSelect(attrs={"data-stripe": "exp-month"})) card_expiry_year = forms.ChoiceField( label=_("Card expiry year"), required=False, widget=NamelessSelect(attrs={'data-stripe': 'exp-year'})) card_ccv = forms.CharField( label=_("CCV"), help_text=_( "A security code, " "usually the last 3 digits found on the back of your card."), required=False, widget=NamelessTextInput(attrs={"data-stripe": "cvc"})) stripeToken = forms.CharField(widget=forms.HiddenInput()) @classmethod def preprocess(cls, data): """ A preprocessor for the order form data, insets stripeToken. The default preprocessor that is called from super handles copying billing fields to shipping fields if "same" checked. StripeToken defaults to None. """ data = super(StripeOrderForm, cls).preprocess(data) # The stripeToken form field is required, hence fill it with something. if ("stripeToken" in data) and (len(data["stripeToken"]) == 0): data["stripeToken"] = "None" return data
def __init__(self, *args, **kwargs): """ Handles adding a variation to the cart or wishlist. When adding from the product page, the product is provided from the view and a set of choice fields for all the product options for this product's variations are added to the form. When the form is validated, the selected options are used to determine the chosen variation. A ``to_cart`` boolean keyword arg is also given specifying whether the product is being added to a cart or wishlist. If a product is being added to the cart, then its stock level is also validated. When adding to the cart from the wishlist page, a sku is given for the variation, so the creation of choice fields is skipped. """ self._product = kwargs.pop("product", None) self._to_cart = kwargs.pop("to_cart") super(AddProductForm, self).__init__(*args, **kwargs) # Adding from the wishlist with a sku, bail out. if args[0] is not None and args[0].get("sku", None): return # Adding from the product page, remove the sku field # and build the choice fields for the variations. del self.fields["sku"] option_fields = ProductVariation.option_fields() if not option_fields: return option_names, option_labels = list( zip(*[(f.name, f.verbose_name) for f in option_fields])) option_values = list( zip(*self._product.variations.filter( unit_price__isnull=False).values_list(*option_names))) if option_values: for i, name in enumerate(option_names): values = [_f for _f in set(option_values[i]) if _f] if values: field = forms.ChoiceField(label=option_labels[i], choices=make_choices(values)) self.fields[name] = field if self._product.content_model == 'reservableproduct': # ReservableProduct needs from/to dates and does not need quantity self.fields["from_date"] = forms.DateField( input_formats=["%d.%m.%Y"], widget=forms.HiddenInput()) self.fields["to_date"] = forms.DateField( input_formats=["%d.%m.%Y"], widget=forms.HiddenInput()) self.fields["quantity"] = forms.IntegerField( min_value=1, initial=1, widget=forms.HiddenInput())
def __init__(self, *args, **kwargs): """ Set the choices for each of the fields for product options. Also remove the current instance from choices for related and upsell products. """ super(ProductAdminForm, self).__init__(*args, **kwargs) for field, options in ProductOption.objects.as_fields().items(): self.fields[field].choices = make_choices(options) instance = kwargs.get("instance") if instance: queryset = Product.objects.exclude(id=instance.id) self.fields["related_products"].queryset = queryset self.fields["upsell_products"].queryset = queryset
def __init__(self, *args, **kwargs): """ Set the choices for each of the fields for product options. Also remove the current instance from choices for related and upsell products (if enabled). """ super(ProductAdminForm, self).__init__(*args, **kwargs) for field, options in list(ProductOption.objects.as_fields().items()): self.fields[field].choices = make_choices(options) instance = kwargs.get("instance") if instance: queryset = Product.objects.exclude(id=instance.id) if settings.SHOP_USE_RELATED_PRODUCTS: self.fields["related_products"].queryset = queryset if settings.SHOP_USE_UPSELL_PRODUCTS: self.fields["upsell_products"].queryset = queryset
def __init__(self, *args, **kwargs): """ Handles adding a variation to the cart or wishlist. When adding from the product page, the product is provided from the view and a set of choice fields for all the product options for this product's variations are added to the form. When the form is validated, the selected options are used to determine the chosen variation. A ``to_cart`` boolean keyword arg is also given specifying whether the product is being added to a cart or wishlist. If a product is being added to the cart, then its stock level is also validated. When adding to the cart from the wishlist page, a sku is given for the variation, so the creation of choice fields is skipped. """ self._product = kwargs.pop("product", None) self._to_cart = kwargs.pop("to_cart") super(AddProductForm, self).__init__(*args, **kwargs) # Adding from the wishlist with a sku, bail out. if args[0] is not None and args[0].get("sku", None): return # Adding from the product page, remove the sku field # and build the choice fields for the variations. del self.fields["sku"] option_fields = ProductVariation.option_fields() if not option_fields: return option_names, option_labels = list(zip(*[(f.name, f.verbose_name) for f in option_fields])) option_values = list(zip(*self._product.variations.filter( unit_price__isnull=False).values_list(*option_names))) if option_values: for i, name in enumerate(option_names): values = [_f for _f in set(option_values[i]) if _f] if values: field = forms.ChoiceField(label=option_labels[i], choices=make_choices(values)) self.fields[name] = field if self._product.content_model == 'reservableproduct': # ReservableProduct needs from/to dates and does not need quantity self.fields["from_date"] = forms.DateField(input_formats=["%d.%m.%Y"], widget=forms.HiddenInput()) self.fields["to_date"] = forms.DateField(input_formats=["%d.%m.%Y"], widget=forms.HiddenInput()) self.fields["quantity"] = forms.IntegerField(min_value=1, initial=1, widget=forms.HiddenInput())
def __init__(self, *args, **kwargs): """ Handles adding a variation to the cart or wishlist. When adding from the product page, the product is provided from the view and a set of choice fields for all the product options for this product's variations are added to the form. When the form is validated, the selected options are used to determine the chosen variation. A ``to_cart`` boolean keyword arg is also given specifying whether the product is being added to a cart or wishlist. If a product is being added to the cart, then its stock level is also validated. When adding to the cart from the wishlist page, a sku is given for the variation, so the creation of choice fields is skipped. """ self._product = kwargs.pop("product", None) self._to_cart = kwargs.pop("to_cart") super(AddProductForm, self).__init__(*args, **kwargs) # Adding from the wishlist with a sku, bail out. if args[0] is not None and args[0].get("sku", None): return # Adding from the product page, remove the sku field # and build the choice fields for the variations. del self.fields["sku"] option_fields = ProductVariation.option_fields() if not option_fields: return option_names, option_labels = zip(*[(f.name, f.verbose_name) for f in option_fields]) option_values = zip(*self._product.variations.filter( unit_price__isnull=False).values_list(*option_names)) if option_values: for i, name in enumerate(option_names): values = list(option_values[i]) try: values.remove(None) except ValueError: pass if values: field = forms.ChoiceField(label=option_labels[i], choices=make_choices(values)) self.fields[name] = field
def __init__(self, *args, **kwargs): """ Create each ChoiceField for selecting from the product's variations. """ self._to_cart = kwargs.pop("to_cart", True) super(AddProductForm, self).__init__(*args, **kwargs) option_names, option_labels = zip(*[(f.name, f.verbose_name) for f in ProductVariation.option_fields()]) option_values = zip(*product.variations.filter( unit_price__isnull=False).values_list(*option_names)) if option_values: for i, name in enumerate(option_names): values = filter(None, set(option_values[i])) if values: field = forms.ChoiceField(label=option_labels[i], choices=make_choices(values)) self.fields[name] = field
def __init__(self, request, step, data=None, initial=None, errors=None): OrderForm.__init__(self, request, step, data, initial, errors) is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT # Get list of country names countries = make_choices(get_country_names_list()) if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Change country widgets to a Select widget self.fields["billing_detail_country"].widget = forms.Select( choices=countries) self.fields[ "billing_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY self.fields["shipping_detail_country"].widget = forms.Select( choices=countries) self.fields[ "shipping_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY if is_payment_step: # Make card number and cvv fields use the data encrypted widget self.fields["card_number"].widget = DataEncryptedTextInput() self.fields["card_ccv"].widget = DataEncryptedPasswordInput() else: # Change country widgets to a Select widget self.fields["billing_detail_country"].widget = forms.Select( choices=countries) self.fields[ "billing_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY self.fields["shipping_detail_country"].widget = forms.Select( choices=countries) self.fields[ "shipping_detail_country"].initial = settings.SHOP_DEFAULT_COUNTRY if settings.SHOP_PAYMENT_STEP_ENABLED: # Make card number and cvv fields use the data encrypted widget self.fields["card_number"].widget = DataEncryptedTextInput() self.fields["card_ccv"].widget = DataEncryptedPasswordInput()
def __init__(self, request, step, data=None, initial=None, errors=None): """ Setup for each order form step which does a few things: - Calls OrderForm.preprocess on posted data - Sets up any custom checkout errors - Hides the discount code field if applicable - Hides sets of fields based on the checkout step - Sets year choices for cc expiry field based on current date """ # ``data`` is usually the POST attribute of a Request object, # which is an immutable QueryDict. We want to modify it, so we # need to make a copy. data = copy(data) # Force the specified step in the posted data, which is # required to allow moving backwards in steps. Also handle any # data pre-processing, which subclasses may override. if data is not None: data["step"] = step data = self.preprocess(data) if initial is not None: initial["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors # Hide discount code field if it shouldn't appear in checkout, # or if no discount codes are active. settings.use_editable() if not (settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT and DiscountCode.objects.active().exists()): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. # A ``hidden_filter`` function is defined that's used for # filtering out the fields to hide. is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT hidden_filter = lambda f: False if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Hide cc fields for billing/shipping if steps are split. hidden_filter = lambda f: f.startswith("card_") elif is_payment_step: # Hide non-cc fields for payment if steps are split. hidden_filter = lambda f: not f.startswith("card_") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all cc fields if payment step is not enabled. hidden_filter = lambda f: f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and is_last_step: # Hide all fields for the confirmation step. hidden_filter = lambda f: True for field in filter(hidden_filter, self.fields): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False if settings.SHOP_ALWAYS_SAME_BILLING_SHIPPING: for field in self.fields: if field == 'same_billing_shipping' or field.startswith( 'shipping_'): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set year choices for cc expiry, relative to the current year. year = now().year choices = make_choices(list(range(year, year + 21))) self.fields["card_expiry_year"].choices = choices
def __init__(self, request, step, data=None, initial=None, errors=None): """ Handle setting shipping field values to the same as billing field values in case JavaScript is disabled, hiding fields for the current step. """ get_saved_card = True # Copy billing fields to shipping fields if "same" checked. first = step == checkout.CHECKOUT_STEP_FIRST last = step == checkout.CHECKOUT_STEP_LAST if (first and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when # moving backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is # required to allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors settings.use_editable() # Hide Discount Code field if no codes are active. if (DiscountCode.objects.active().count() == 0 or not settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if first: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits" or f == "use_saved_card") get_saved_card = False elif step == checkout.CHECKOUT_STEP_PAYMENT: # TODO: If this user has a stripe customer object, get it and the saved card # Allow user to use saved card. # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all the cc fields if payment step is not enabled. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits" or f == "use_saved_card") get_saved_card = False if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and last: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False hide_saved_card = True hide_card_save_options = True if not settings.ALLOW_SAVED_CREDIT_CARDS: get_saved_card = False if get_saved_card: #Get stripe customer and their saved card if request.user.is_authenticated(): User = request.user customer = getStripeCustomerFromUser(User) hide_card_save_options = False if customer.cards.count > 0: brand,last4 = getBrandAndLast4OfDefaultCard(customer) if brand is not None and last4 is not None: self.fields['use_saved_card'].label = "Use {} ending in {}".format(brand, last4) hide_saved_card = False if hide_saved_card: self.fields['use_saved_card'].widget = forms.HiddenInput() if hide_card_save_options: self.fields['card_save_card'].widget = forms.HiddenInput() # Set the choices for the cc expiry year relative to the current year. year = now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices
class OrderForm(FormsetForm, DiscountForm): """ Main Form for the checkout process - ModelForm for the Order Model with extra fields for credit card. Used across each step of the checkout process with fields being hidden where applicable. """ step = forms.IntegerField(widget=forms.HiddenInput()) same_billing_shipping = forms.BooleanField( required=False, initial=True, label=_("My delivery details are the same as my billing details")) remember = forms.BooleanField(required=False, initial=True, label=_("Remember my address for next time")) card_name = forms.CharField(label=_("Cardholder name")) card_type = forms.ChoiceField(label=_("Card type"), widget=forms.RadioSelect, choices=make_choices( settings.SHOP_CARD_TYPES)) card_number = forms.CharField(label=_("Card number")) card_expiry_month = forms.ChoiceField( label=_("Card expiry month"), initial="%02d" % date.today().month, choices=make_choices(["%02d" % i for i in range(1, 13)])) card_expiry_year = forms.ChoiceField(label=_("Card expiry year")) card_ccv = forms.CharField( label=_("CCV"), help_text=_( "A security code, " "usually the last 3 digits found on the back of your card.")) #import captcha #wni_captcha = captcha.fields.CaptchaField() prefer_time = WniChoiceField(label="配送时间", widget=forms.RadioSelect, choices=((u"立即送餐", u"立即送餐(1小时之内)"), (u"预约", u"预约送达时间")), initial=u"立即送餐") #pay_type=WniChoiceField(label="支付方式",widget=forms.RadioSelect,choices=((u"货到付款",u"货到付款"),),initial=u"货到付款") pay_type = WniChoiceField(label="支付方式", widget=forms.RadioSelect, choices=((u"货到付款", u"货到付款"), (u"微信支付", u"微信支付")), initial=u"货到付款") delivery_type = WniComplexChoiceField( label="配送方式", wnichoices=settings.CENTER_POTS['Nanjing']) #,initial=u"efoodin冷链配送") class Meta: model = Order """ fields = ([f.name for f in Order._meta.fields if f.name.startswith("billing_detail") or f.name.startswith("shipping_detail")] + ["additional_instructions", "discount_code"]) """ fields = ([ f.name for f in Order._meta.fields if f.name in [ "billing_detail_first_name", "billing_detail_phone", "billing_detail_email", "billing_detail_street", "prefer_time", "delivery_type", "pay_type", "shipping_detail_first_name", "shipping_detail_phone", "shipping_detail_street" ] ] + ["additional_instructions", "discount_code"]) """ fields = ([f.name for f in Order._meta.fields if f.name in ["billing_detail_first_name","billing_detail_phone","billing_detail_email"] ] + ["additional_instructions", "discount_code"]) """ def __init__(self, request, step, data=None, initial=None, errors=None): """ Setup for each order form step which does a few things: - Calls OrderForm.preprocess on posted data - Sets up any custom checkout errors - Hides the discount code field if applicable - Hides sets of fields based on the checkout step - Sets year choices for cc expiry field based on current date """ # ``data`` is usually the POST attribute of a Request object, # which is an immutable QueryDict. We want to modify it, so we # need to make a copy. data = copy(data) # Force the specified step in the posted data, which is # required to allow moving backwards in steps. Also handle any # data pre-processing, which subclasses may override. if data is not None: data["step"] = step data = self.preprocess(data) if initial is not None: initial["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors # Hide discount code field if it shouldn't appear in checkout, # or if no discount codes are active. settings.use_editable() if not (settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT and DiscountCode.objects.active().exists()): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. # A ``hidden_filter`` function is defined that's used for # filtering out the fields to hide. is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT hidden_filter = lambda f: False if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Hide cc fields for billing/shipping if steps are split. hidden_filter = lambda f: f.startswith("card_") elif is_payment_step: # Hide non-cc fields for payment if steps are split. hidden_filter = lambda f: not f.startswith("card_") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all cc fields if payment step is not enabled. hidden_filter = lambda f: f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and is_last_step: # Hide all fields for the confirmation step. hidden_filter = lambda f: True for field in filter(hidden_filter, self.fields): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set year choices for cc expiry, relative to the current year. year = now().year choices = make_choices(list(range(year, year + 21))) self.fields["card_expiry_year"].choices = choices #self.fields['prefer_time'].widget = forms.DateTimeInput() #self.fields['prefer_time']=WniChoiceField(label="配送时间",widget=forms.RadioSelect,choices=((u"立即送餐",u"立即送餐"),(u"预约",u"预约"))) #self.fields['prefer_time'].widget = forms.RadioSelect(choices=((u"立即送餐",u"立即送餐"),(u"预约",u"预约"))) #self.fields['prefer_time'].widget = widgets.AdminSplitDateTime() if settings.WITH_WEIXIN_PAY and 'micromessenger' in request.META.get( 'HTTP_USER_AGENT').lower(): self.fields["pay_type"].choices = ((u"货到付款", u"货到付款"), (u"微信支付", u"微信支付")) else: self.fields["pay_type"].choices = ((u"货到付款", u"货到付款"), ) @classmethod def preprocess(cls, data): """ A preprocessor for the order form data that can be overridden by custom form classes. The default preprocessor here handles copying billing fields to shipping fields if "same" checked. """ if data.get("same_billing_shipping", "") == "on": #wni: change on to shit for field in data: bill_field = field.replace("shipping_detail", "billing_detail") if field.startswith("shipping_detail") and bill_field in data: data[field] = data[bill_field] return data def clean_card_expiry_year(self): """ Ensure the card expiry doesn't occur in the past. """ try: month = int(self.cleaned_data["card_expiry_month"]) year = int(self.cleaned_data["card_expiry_year"]) except ValueError: # Haven't reached payment step yet. return n = now() if year == n.year and month < n.month: raise forms.ValidationError(_("A valid expiry date is required.")) return str(year) def clean(self): """ Raise ``ValidationError`` if any errors have been assigned externally, via one of the custom checkout step handlers. """ if self._checkout_errors: raise forms.ValidationError(self._checkout_errors) return super(OrderForm, self).clean()
def __init__(self, request, step, data=None, initial=None, errors=None): """ Setup for each order form step which does a few things: - Calls OrderForm.preprocess on posted data - Sets up any custom checkout errors - Hides the discount code field if applicable - Hides sets of fields based on the checkout step - Sets year choices for cc expiry field based on current date """ # ``data`` is usually the POST attribute of a Request object, # which is an immutable QueryDict. We want to modify it, so we # need to make a copy. data = copy(data) # Force the specified step in the posted data, which is # required to allow moving backwards in steps. Also handle any # data pre-processing, which subclasses may override. if data is not None: data["step"] = step data = self.preprocess(data) if initial is not None: initial["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors # Hide discount code field if it shouldn't appear in checkout, # or if no discount codes are active. settings.use_editable() if not (settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT and DiscountCode.objects.active().exists()): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. # A ``hidden_filter`` function is defined that's used for # filtering out the fields to hide. is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT hidden_filter = lambda f: False if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Hide cc fields for billing/shipping if steps are split. hidden_filter = lambda f: f.startswith("card_") elif is_payment_step: # Hide non-cc fields for payment if steps are split. hidden_filter = lambda f: not f.startswith("card_") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all cc fields if payment step is not enabled. hidden_filter = lambda f: f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and is_last_step: # Hide all fields for the confirmation step. hidden_filter = lambda f: True for field in filter(hidden_filter, self.fields): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set year choices for cc expiry, relative to the current year. year = now().year choices = make_choices(list(range(year, year + 21))) self.fields["card_expiry_year"].choices = choices
class OrderForm(FormsetForm, DiscountForm): """ Main Form for the checkout process - ModelForm for the Order Model with extra fields for credit card. Used across each step of the checkout process with fields being hidden where applicable. """ step = forms.IntegerField(widget=forms.HiddenInput()) same_billing_shipping = forms.BooleanField(required=False, initial=True, label=_("My delivery details are the same as my billing details")) remember = forms.BooleanField(required=False, initial=True, label=_("Remember my address for next time")) card_name = forms.CharField(label=_("Cardholder name")) card_type = forms.ChoiceField(widget=forms.RadioSelect, choices=make_choices(settings.SHOP_CARD_TYPES)) card_number = forms.CharField() card_expiry_month = forms.ChoiceField( initial="%02d" % date.today().month, choices=make_choices(["%02d" % i for i in range(1, 13)])) card_expiry_year = forms.ChoiceField() card_ccv = forms.CharField(label="CCV", help_text=_("A security code, " "usually the last 3 digits found on the back of your card.")) class Meta: model = Order fields = ([f.name for f in Order._meta.fields if f.name.startswith("billing_detail") or f.name.startswith("shipping_detail")] + ["additional_instructions", "discount_code"]) def __init__(self, request, step, data=None, initial=None, errors=None): """ Handle setting shipping field values to the same as billing field values in case JavaScript is disabled, hiding fields for the current step. """ # Copy billing fields to shipping fields if "same" checked. first = step == checkout.CHECKOUT_STEP_FIRST last = step == checkout.CHECKOUT_STEP_LAST if (first and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when # moving backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is # required to allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors settings.use_editable() # Hide Discount Code field if no codes are active. if (DiscountCode.objects.active().count() == 0 or not settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if first: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: f.startswith("card_") elif step == checkout.CHECKOUT_STEP_PAYMENT: # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not f.startswith("card_") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all the cc fields if payment step is not enabled. hidden = lambda f: f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and last: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set the choices for the cc expiry year relative to the current year. year = now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices def clean_card_expiry_year(self): """ Ensure the card expiry doesn't occur in the past. """ try: month = int(self.cleaned_data["card_expiry_month"]) year = int(self.cleaned_data["card_expiry_year"]) except ValueError: # Haven't reached payment step yet. return n = now() if year == n.year and month < n.month: raise forms.ValidationError(_("A valid expiry date is required.")) return str(year) def clean(self): """ Raise ``ValidationError`` if any errors have been assigned externally, via one of the custom checkout step handlers. """ if self._checkout_errors: raise forms.ValidationError(self._checkout_errors) return self.cleaned_data
def __init__(self, request, step, data=None, initial=None, errors=None): """ Handle setting shipping field values to the same as billing field values in case JavaScript is disabled, hiding fields for the current step. """ # Copy billing fields to shipping fields if "same" checked. first = step == checkout.CHECKOUT_STEP_FIRST last = step == checkout.CHECKOUT_STEP_LAST if (first and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when # moving backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is # required to allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors settings.use_editable() # Hide Discount Code field if no codes are active. if (DiscountCode.objects.active().count() == 0 or not settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if first: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") elif step == checkout.CHECKOUT_STEP_PAYMENT: # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all the cc fields if payment step is not enabled. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and last: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set the choices for the cc expiry year relative to the current year. year = now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices
class OrderForm(FormsetForm, DiscountForm): """ Main Form for the checkout process - ModelForm for the Order Model with extra fields for credit card. Used across each step of the checkout process with fields being hidden where applicable. """ step = forms.IntegerField(widget=forms.HiddenInput()) same_billing_shipping = forms.BooleanField( required=False, initial=True, label=_("My delivery details are the same as my billing details")) remember = forms.BooleanField(required=False, initial=True, label=_("Remember my address for next time")) card_name = forms.CharField(label=_("Cardholder name")) card_type = forms.ChoiceField(widget=forms.RadioSelect, choices=make_choices( settings.SHOP_CARD_TYPES)) card_number = forms.CharField(required=False, max_length=20, widget=NoNameTextInput()) card_cvv = forms.CharField(required=False, max_length=4, widget=NoNameTextInput()) card_expiry_month = forms.ChoiceField(required=False, widget=NoNameSelect(), choices=MONTHS.iteritems()) card_expiry_year = forms.ChoiceField( required=False, widget=NoNameSelect(), choices=options.ZEBRA_CARD_YEARS_CHOICES) last_4_digits = forms.CharField(required=True, min_length=4, max_length=4, widget=forms.HiddenInput()) stripe_token = forms.CharField(required=True, widget=forms.HiddenInput()) def addError(self, message): self._errors[NON_FIELD_ERRORS] = self.error_class([message]) class Meta: model = Order fields = ([ f.name for f in Order._meta.fields if f.name.startswith("billing_detail") or f.name.startswith("shipping_detail") ] + ["additional_instructions", "discount_code"]) def __init__(self, request, step, data=None, initial=None, errors=None): """ Handle setting shipping field values to the same as billing field values in case JavaScript is disabled, hiding fields for the current step. """ # Copy billing fields to shipping fields if "same" checked. first = step == checkout.CHECKOUT_STEP_FIRST last = step == checkout.CHECKOUT_STEP_LAST if (first and data is not None and "same_billing_shipping" in data): data = copy(data) # Prevent second copy occuring for forcing step below when # moving backwards in steps. data["step"] = step for field in data: billing = field.replace("shipping_detail", "billing_detail") if "shipping_detail" in field and billing in data: data[field] = data[billing] if initial is not None: initial["step"] = step # Force the specified step in the posted data - this is # required to allow moving backwards in steps. if data is not None and int(data["step"]) != step: data = copy(data) data["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors settings.use_editable() # Hide Discount Code field if no codes are active. if (DiscountCode.objects.active().count() == 0 or not settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. hidden = None if settings.SHOP_CHECKOUT_STEPS_SPLIT: if first: # Hide the cc fields for billing/shipping if steps are split. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") elif step == checkout.CHECKOUT_STEP_PAYMENT: # Hide the non-cc fields for payment if steps are split. hidden = lambda f: not (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all the cc fields if payment step is not enabled. hidden = lambda f: (f.startswith("card_") or f == "stripe_token" or f == "last_4_digits") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and last: # Hide all fields for the confirmation step. hidden = lambda f: True if hidden is not None: for field in self.fields: if hidden(field): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set the choices for the cc expiry year relative to the current year. year = now().year choices = make_choices(range(year, year + 21)) self.fields["card_expiry_year"].choices = choices def clean(self): """ Raise ``ValidationError`` if any errors have been assigned externally, via one of the custom checkout step handlers. """ if self._checkout_errors: raise forms.ValidationError(self._checkout_errors) return self.cleaned_data
class OrderForm(FormsetForm, DiscountForm): """ Main Form for the checkout process - ModelForm for the Order Model with extra fields for credit card. Used across each step of the checkout process with fields being hidden where applicable. """ step = forms.IntegerField(widget=forms.HiddenInput()) same_billing_shipping = forms.BooleanField( required=False, initial=True, label=_("My delivery details are the same as my billing details")) remember = forms.BooleanField(required=False, initial=True, label=_("Remember my address for next time")) card_name = forms.CharField(label=_("Cardholder name")) card_type = forms.ChoiceField(label=_("Card type"), widget=forms.RadioSelect, choices=make_choices( settings.SHOP_CARD_TYPES)) card_number = forms.CharField(label=_("Card number")) card_expiry_month = forms.ChoiceField( label=_("Card expiry month"), initial="%02d" % date.today().month, choices=make_choices(["%02d" % i for i in range(1, 13)])) card_expiry_year = forms.ChoiceField(label=_("Card expiry year")) card_ccv = forms.CharField( label=_("CCV"), help_text=_( "A security code, " "usually the last 3 digits found on the back of your card.")) class Meta: model = Order fields = ([ f.name for f in Order._meta.fields if (f.name.startswith("billing_detail") or f.name.startswith("shipping_detail")) and f.name.replace( "billing_detail_", "").replace("shipping_detail_", "") not in settings.SHOP_HIDE_BILLING_SHIPPING_FIELDS ] + [ "additional_instructions", "discount_code", "persons_adults", "persons_childs" ]) def __init__(self, request, step, data=None, initial=None, errors=None): """ Setup for each order form step which does a few things: - Calls OrderForm.preprocess on posted data - Sets up any custom checkout errors - Hides the discount code field if applicable - Hides sets of fields based on the checkout step - Sets year choices for cc expiry field based on current date """ # ``data`` is usually the POST attribute of a Request object, # which is an immutable QueryDict. We want to modify it, so we # need to make a copy. data = copy(data) # Force the specified step in the posted data, which is # required to allow moving backwards in steps. Also handle any # data pre-processing, which subclasses may override. if data is not None: data["step"] = step data = self.preprocess(data) if initial is not None: initial["step"] = step super(OrderForm, self).__init__(request, data=data, initial=initial) self._checkout_errors = errors # Hide discount code field if it shouldn't appear in checkout, # or if no discount codes are active. settings.use_editable() if not (settings.SHOP_DISCOUNT_FIELD_IN_CHECKOUT and DiscountCode.objects.active().exists()): self.fields["discount_code"].widget = forms.HiddenInput() # Determine which sets of fields to hide for each checkout step. # A ``hidden_filter`` function is defined that's used for # filtering out the fields to hide. is_first_step = step == checkout.CHECKOUT_STEP_FIRST is_last_step = step == checkout.CHECKOUT_STEP_LAST is_payment_step = step == checkout.CHECKOUT_STEP_PAYMENT hidden_filter = lambda f: False if settings.SHOP_CHECKOUT_STEPS_SPLIT: if is_first_step: # Hide cc fields for billing/shipping if steps are split. hidden_filter = lambda f: f.startswith("card_") elif is_payment_step: # Hide non-cc fields for payment if steps are split. hidden_filter = lambda f: not f.startswith("card_") elif not settings.SHOP_PAYMENT_STEP_ENABLED: # Hide all cc fields if payment step is not enabled. hidden_filter = lambda f: f.startswith("card_") if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION and is_last_step: # Hide all fields for the confirmation step. hidden_filter = lambda f: True for field in filter(hidden_filter, self.fields): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False if settings.SHOP_ALWAYS_SAME_BILLING_SHIPPING: for field in self.fields: if field == 'same_billing_shipping' or field.startswith( 'shipping_'): self.fields[field].widget = forms.HiddenInput() self.fields[field].required = False # Set year choices for cc expiry, relative to the current year. year = now().year choices = make_choices(list(range(year, year + 21))) self.fields["card_expiry_year"].choices = choices @classmethod def preprocess(cls, data): """ A preprocessor for the order form data that can be overridden by custom form classes. The default preprocessor here handles copying billing fields to shipping fields if "same" checked. """ if data.get("same_billing_shipping", "") == "on": for field in data: bill_field = field.replace("shipping_detail", "billing_detail") if field.startswith("shipping_detail") and bill_field in data: data[field] = data[bill_field] return data def clean_card_expiry_year(self): """ Ensure the card expiry doesn't occur in the past. """ try: month = int(self.cleaned_data["card_expiry_month"]) year = int(self.cleaned_data["card_expiry_year"]) except ValueError: # Haven't reached payment step yet. return n = now() if year == n.year and month < n.month: raise forms.ValidationError(_("A valid expiry date is required.")) return str(year) def clean(self): """ Raise ``ValidationError`` if any errors have been assigned externally, via one of the custom checkout step handlers. """ if self._checkout_errors: raise forms.ValidationError(self._checkout_errors) # Validate necessary fields are filled since hideable fields are # blank=True in the Order model for field in self.fields: if (field.startswith("billing_detail") or (field.startswith("shipping_detail") and not settings.SHOP_ALWAYS_SAME_BILLING_SHIPPING) ) and len(self.data[field]) == 0 and field.replace( "billing_detail_", "").replace( "shipping_detail_", "") not in settings.SHOP_HIDE_BILLING_SHIPPING_FIELDS: self.errors[field] = [_("This field is required.")] raise forms.ValidationError(_("Please fill out all fields.")) return super(OrderForm, self).clean()