首页 文章

使用Django条带化 - 使表单clean()方法返回不是表单字段的值

提问于
浏览
1

我正在将Stripe支付处理集成到我的Django应用程序中,我无法找出验证客户卡信息的“正确”方法,并在包含用户条带客户ID的Users表中插入一行 .

理想情况下,我喜欢按照以下方式执行某些操作,其中我的CheckoutForm会验证卡详细信息,如果不正确则会引发表单ValidationError . 但是,使用这个解决方案,我无法找到一种方法来获取clean()函数生成的customer.id .

forms.py

class CheckoutForm(forms.Form):
    email = forms.EmailField(label='E-mail address', max_length=128, widget=forms.EmailInput(attrs={'class': 'form-control'}))
    stripe_token = forms.CharField(label='Stripe token', widget=forms.HiddenInput)

    def clean(self):
        cleaned_data = super().clean()
        stripe_token = cleaned_data.get('stripe_token')
        email = cleaned_data.get('email')

        try:

            customer = stripe.Customer.create(
                email=email,
                source=stripe_token,
            )
            // I can now get a customer.id from this 'customer' variable, which I want to insert into my database

        except:
            raise forms.ValidationError("It looks like your card details are incorrect!")

views.py

# If the form is valid...
if form.is_valid():

    # Create a new user
        user = get_user_model().objects.create_user(email=form.cleaned_data['email'], stripe_customer_id=<<<I want the customer.id generated in my form's clean() method to go here>>>)
        user.save()

我能想到的唯一其他解决方案是在验证表单后运行views.py中的stripe.Customer.create()函数 . 那个'll work, but it doesn'似乎是'right'编码事物的方式,因为据我所知,表单字段的所有验证都应该在forms.py中完成 .

在这种情况下,正确的Django编码实践是什么?我应该将我的卡验证代码移动到views.py,还是有更简洁的方法将卡验证代码保存在forms.py中并从中获取customer.id?

1 回答

  • 2

    在这种情况下,我不认为正确的Django编码实践与Python编码实践有任何不同 . 由于Django表单只是一个类,因此可以为 customer 定义属性 . 像这样的东西:

    class CheckoutForm(forms.Form):
        email = forms.EmailField(label='E-mail address', max_length=128, widget=forms.EmailInput(attrs={'class': 'form-control'}))
        stripe_token = forms.CharField(label='Stripe token', widget=forms.HiddenInput)
    
        _customer = None
    
        def clean(self):
            cleaned_data = super().clean()
            stripe_token = cleaned_data.get('stripe_token')
            email = cleaned_data.get('email')  
    
            try:
                self.customer = stripe.Customer.create(
                    email=email,
                    source=stripe_token,
                )
            except:
                raise forms.ValidationError("It looks like your card details are incorrect!")
    
        @property
        def customer(self):
            return self._customer
    
        @customer.setter
        def customer(self, value):
            self._customer = value
    

    然后是 form.is_valid() 之后的 views.py ,你要调用这个属性 .

    if form.is_valid():
        customer = form.customer
    

    或者 @property 可能是一种矫枉过正,您可以这样做:

    class CheckoutForm(forms.Form):
        email = forms.EmailField(label='E-mail address', max_length=128, widget=forms.EmailInput(attrs={'class': 'form-control'}))
        stripe_token = forms.CharField(label='Stripe token', widget=forms.HiddenInput)
    
        customer = None
    
        def clean(self):
            cleaned_data = super().clean()
            stripe_token = cleaned_data.get('stripe_token')
            email = cleaned_data.get('email')  
    
            try:
                self.customer = stripe.Customer.create(
                    email=email,
                    source=stripe_token,
                )
            except:
                raise forms.ValidationError("It looks like your card details are incorrect!")
    

    ......仍然 form.customerviews.py .

    我想两者都应该有效,但我没有测试过代码 .

相关问题