简短版:在 django 网站上,我可以从 Twilio 的请求中获取值,request.GET
但不能request.POST
响应。我怀疑它与csrf有关,但我不确定如何调试问题。详情如下。
长版: 我正在帮助一位朋友完成一个项目,我们正在使用 Twilio REST API 通过 SMS 进行医学调查。我有一个域和一个非常简单的 django 构建的站点,我构建它只是为了更好地熟悉 django,所以我们正在使用它。
我们正在收集对我们的调查的 SMS 响应,作为 Twilio API 的一部分,它会将对我们号码的任何响应发送到帐户下指定的 url,因此我们的响应目标类似于以下内容:
...mydomain.com/some_page/another_page/
然后,Twilio 请求如下所示:
...mydomain.com/some_page/another_page/?AccountSid=###SOME_LONG_ACCOUNT_SIDE&From=%2BPHONE_NUMBER&Body=bla+BLA+bla+BLA&SmsSid=##MESSAGE_ID_KEY&SmsMessageSid=##MESSAGE_ID_KEY&FromCity=Santa+Cruz&FromState=California...
工作代码
我正在测试传入的请求是否包含AccountSid
在其中(与数据库中的值相比),并且在我views.py
的应用程序中,我有如下所示的内容(并且可行):
from our_app import TwilioAccount
our_account = TwilioAccount.objects.get(id=1)
def twilio_response(request):
assert request.GET.get('AccountSid', None) == our_account.account_sid
## log the incoming request to the database under survey responses...
非工作代码
如果我登录到我们的 Twilio 帐户并将请求方法切换到POST
,然后我将所有数据收集切换到request.POST
,则上述断言语句将失败。进一步调试发现我的 QueryDict 在 POST, 下是空的POST: {}
,所以没有抓取到键值。
我认为这可能是因为POST
在 django 下需要 a csrf_token
,但我认为检查 AccountSid 相当好,所以我导入csrf_exempt
并用它包装了上面的函数:
@csrf_exempt
def twilio_response(request):
assert request.POST.get('AccountSid', None) == our_account.account_sid
## log the incoming request to the database under survey responses...
AssertionError: ...
这不适用于完全相同的请求:QueryDict 为空。
问题:
1)我还需要做些什么来完成我的@csrf_exempt
工作吗?另一个问题:这是一种可怕而愚蠢的方法吗?当使用其他公司的 API 而不是实际的登录用户时,人们通常如何满足这一要求?
1a) 与其将其设为 csrf_exempt,不如将其保留为GET
请求,因为它仍在检查所有传入请求是否与我们的 account_sid 相对应。我应该这样做还是这样做真的很幼稚?
2)我渴望学习做到这一点的最佳方法:我是否应该构建一个 django 表单,然后将请求路由到我的表单并测试有效性并以这种方式清理数据?如果是这样,当没有表单模板时,谁能给我一个关于视图/表单外观的粗略大纲(完整的 csrf_token)?