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

时间:2017-12-14 21:52:37

标签: django forms validation django-forms stripe-payments

我正在将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()函数。这样做有用,但它似乎不是编码事物的“正确”方式,因为据我所知,表单字段的所有验证都应该在forms.py中完成。

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

1 个答案:

答案 0 :(得分: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

然后在views.py之后form.is_valid(),您将此属性称为。

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.customer中仍然是views.py

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