【发布时间】:2020-09-26 01:59:07
【问题描述】:
我正在尝试在我的网站上使用订阅表单。我正在使用条纹。我可以使用他们的 API 将数据发送到 Stripe。但是,从 Stripe 接收数据后,我无法将数据保存在服务器端:
// In subscription.js:
$( function() {
var customerEmail = document.querySelector("[data-email]").getAttribute('data-email');
var submissionURL = document.querySelector("[data-redirect]").getAttribute('data-redirect');
var stripeSubscriptionForm = document.getElementById('subscriptionId');
var cardElement = elements.create("card", { style: style });
// Mounting the card element in the template
cardElement.mount("#card-element");
stripeSubscriptionForm.addEventListener('submit', function(event){
event.preventDefault(); // Before submitting, we need to send the data to our database too
theForm = event.target; // getting the form; same as using getElementById, but using the event only
theFormData = new FormData(theForm);
stripe.createPaymentMethod( { type : 'card', // this is what's sent to stripe
card : cardElement,
billing_details : { email : customerEmail, }
},
)
.then( (result) => { // Once stripe returns the result
// Building the data
theFormData.append('card', cardElement);
theFormData.append('billing_details', customerEmail);
theFormData.append('payement_method', result.paymentMethod.id);
// Setting up the request
const xhr = new XMLHttpRequest() // Creating an XHR request object
xhr.open(method, url); // Creating a GET request
// Setting up the header
xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest"); // Ajax header
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); // Ajax header
xhr.setRequestHeader("X-CSRF-TOKEN", "{{ csrf_token }}"); // csrf_token
xhr.onload = function() { // After server sends response data back
console.log('Got something back from server ')
const response = xhr.response; // 1) get the response object of the XHR request object
if (xhr.status === 201 ){ // If the item is created
const responseJson = JSON.parse(response)
console.log('and json response: ', responseJson);
}
else{
console.log('httpRequest status: ', httpRequest.status); // Let's see what's going on
}
}
// Sending the form data
xhr.send(theFormData); // Sending the xhr request
});
});
那么,在我的views.py中:
def post(self, request, *args, **kwargs):
''' Receives the subscription form '''
subscriber_form = SubscriberForm(request.POST)
billing_address_form = CompanyAddressForm(request.POST)
subscription_form = SubscriptionForm(request.POST)
if subscriber_form.is_valid() and billing_address_form.is_valid() and subscription_form.is_valid():
print ('forms are valid')
billing_address = billing_address_form.save()
subscriber_instance = subscriber_form.save(commit = False)
subscriber_instance.address = billing_address
print ('######################################################')
if request.META.get('CONTENT_TYPE', '').lower() == 'application/json' and len(request.body) > 0:
print ('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
try:
body_data = json.loads(request.body)
print (body_data)
except Exception as e:
request_body = request.body
print (request_body)print ('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
else:
print ("request.META.get('CONTENT_TYPE', ''): ", request.META.get('CONTENT_TYPE', '') )
## Creating a customer in stripe: Need the data from the front-end:
customer_stripe = stripe.Customer.create( payment_method = data.get('payment_method', None),
email = data.get('email', None),
invoice_settings = { 'default_payment_method': data.get('payment_method', None), },
)
## Creating a subscription in stripe
subscription = stripe.Subscription.create( customer = customer_stripe.id, items = [{'plan': plan_idx, }], # plan_idx is the plan id from stripe
expand = ['latest_invoice.payment_intent'] )
form = SubscriptionForm(request.POST)
if form.is_valid():
subscription_instance = form.save()
else:
context['form'] = SubscriptionForm(request.POST)
return render(request, self.template_name, context)
## Creating the same customer for ourselves
user = request.user
...
customer, created = Customer.objects.get_or_create(...)
return render(request, reverse('dashboard') )
else:
... # Re-render the forms with errors
return render(request, self.template_name, context)
问题是我明白了:
######################################################
request.META.get('CONTENT_TYPE', ''): multipart/form-data; boundary=----WebKitFormBoundaryIeaE9GpJ2EXQBkZK
如何访问我的数据?我的表单都没有图像或文件,但即使我的表单是多部分/表单数据,我将来可能需要向订阅者添加头像,我如何使用body_data = json.loads(request.body) 获取数据?
编辑 1: 所以,我想既然我已经访问了请求对象以在 post 方法中获取我的表单,我可能应该首先准备 request.body,因为 Django 抱怨一旦你触摸请求对象,你就无法再次读取流。所以,这里是修改:
def post(self, request, *args, **kwargs):
''' Receives the subscription form '''
request_body = request.body
try:
body_data = json.loads(request_body)
except Exception as e:
print ('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
print (request_body)
print ('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
但这会返回
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
request_body: b'------WebKitFormBoundaryBBzJCNQS96b76EKx\r\nContent-Disposition: form-data; name="csrfmiddlewaretoken"\r\n\r\n0ryuWTIxVRPjDGe0c9Fxj7Sc3KeCmBtAkiFK5EAlriY0QtAmwo6ip\r\n------WebKitFormBoundaryBBzJCNQS96b76EKx\r\nContent-Disposition: form-data; name="name"\r\n\r\nABC\r\n------WebKitFormBoundaryBBzJCNQS96b76EKx\r\nContent-Disposition: form-data; name="email"\r\n\r\nemail@gmail.com\r\n...'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
问题是为什么会引发异常,这个 WebKitFormBoundary 业务是什么?
编辑 2 因此,当我在服务器端打印 POST 请求时,我确实得到了数据:
def post(self, request, *args, **kwargs):
''' Receives the subscription form '''
# request_body = request.body
print ('request_post: ', request.POST)
print ('')
在我的控制台中返回以下内容:
request_post: <QueryDict: {'csrfmiddlewaretoken': ['OOPVcfGU2WfcPl3ld-Jx1L7XI1vSHfFhp0v1SIzQHpIyWrrhrH0d03HYnS7DdssZ'], 'name': ['ABC'], 'email': ['email@gmail.com'],...
但是,当我发布 request.body 时,我得到:
request_body: b'------WebKitFormBoundaryG87zmkiNu0fTWY0g\r\nContent-Disposition: form-data; name="csrfmiddlewaretoken"\r\n\r\nOOPVcfGU2WfcPl3ld-Jx1L7XI1vSHfFhp0v1SIzQHpIyWrrhrH0d03HYnS7DdssZ\r\n------WebKitFormBoundaryG87zmkiNu0fTWY0g\r\nContent-Disposition: form-data; name="name"\r\n\r\nABC\r\n------WebKitFormBoundaryG87zmkiNu0fTWY0g\r\nContent-Disposition: form-data; name="email"\r\n\r\nemail@gmail.com\r\n------WebKitFormBoundaryG87zmkiNu0fTWY0g\r\n...'
那么,这是否告诉我们数据正在进入服务器端,并且在检索数据时出现问题?
【问题讨论】:
-
你为什么用
GET方法发送你的数据并试图在你的视图中得到它的body? -
你怎么说我用了GET?我确实看过,我正在使用 POST 请求
-
它在您的 javascript 代码中显示为
xhr.open(method, url); // Creating a GET request。当您想要访问已发布给您的数据时。您可以通过variable = request.POST["name_of_data_field"]或更好的版本variable = request.POST.get("name_of_data_field", None)而不是request.body进行操作 -
@Mahyar,我应该在我的 Django 视图中使用 .POST 是正确的。我发现了为什么我应该使用 .POST 而不是 .body。一般来说,你会使用 .body 来处理 JSON,正如这个答案
https://stackoverflow.com/a/37570142/3549766所建议的那样,如果你能详细说明为什么在这种特殊情况下应该使用 .POST 方法,那么我建议你创建一个答案,我会将其标记为正确答案。这是因为本例中的原因可以帮助其他人处理 Ajax、JSON、formData。