Python Django QueryDict为空,带有request.POST,但填充在request.GET中
Short version:在django网站上,我可以从Python Django QueryDict为空,带有request.POST,但填充在request.GET中,python,django,twilio,python-2.x,Python,Django,Twilio,Python 2.x,Short version:在django网站上,我可以从请求中获取值。获取但不获取请求。发布以响应Twilio的请求。我怀疑它与csrf有关,但我不确定如何调试这个问题。详情如下 长版本: 我正在帮助一位朋友进行一个项目,我们正在使用Twilio REST API通过短信进行医疗调查。我有一个域和一个非常简单的django在该域上构建的站点,我构建这个站点是为了更好地熟悉django,所以我们正在使用它 我们正在收集对我们调查的短信回复,作为Twilio API的一部分,它会将对我们号码的任何
请求中获取值。获取但不获取请求。发布以响应Twilio的请求。我怀疑它与csrf有关,但我不确定如何调试这个问题。详情如下
长版本:
我正在帮助一位朋友进行一个项目,我们正在使用Twilio REST API通过短信进行医疗调查。我有一个域和一个非常简单的django在该域上构建的站点,我构建这个站点是为了更好地熟悉django,所以我们正在使用它
我们正在收集对我们调查的短信回复,作为Twilio API的一部分,它会将对我们号码的任何回复发送到帐户下指定的url,因此我们的回复目标如下:
...mydomain.com/some_page/another_page/
...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...
Twilio请求如下所示:
...mydomain.com/some_page/another_page/
...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
中,对于应用程序,我有如下内容(这是有效的):
非工作代码
如果我登录到我们的Twilio帐户并将请求方法切换到POST
,然后将所有数据收集切换到request.POST
,则上述断言语句将失败。进一步的调试显示,我的QueryDict在POST、POST:{}
下为空,因此没有抓取键值
我认为这可能是因为django下的POST
需要一个csrf\u令牌
,但我认为检查AccountSid相当不错,所以我导入了csrf\u emption
,并用它包装了上述函数:
@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\u豁免
工作?另一个问题:这是一种可怕而愚蠢的方式吗?当使用其他公司的API而不是实际的登录用户时,人们通常如何满足这一要求
1a)我可以将其作为GET
请求保留,而不是将其设置为csrf_豁免,因为我知道它仍在根据我们的帐户sid检查所有传入请求。我应该这样做,还是真的很幼稚
2) 我急切地想知道实现这一点的最佳方法:我是否应该构建一个django表单,然后将请求路由到我的表单,测试有效性并以这种方式清理数据?如果是这样的话,有人能给我一个粗略的轮廓,当没有表单模板时,视图/表单会是什么样子(包括csrf_标记)?在我的选项中,您是否在settings.py中打开了DEBUG(=True)?
在调试模式下,您可以引发异常(引发异常(“”)),然后您可以在页面中看到环境变量,如url、GET、POST等
或者返回HttpResponse(request.POST.dict())
查看post变量。
在这里发布Twilio开发者福音派团队的Matt时,使用crsf_豁免是一种正确的方法
1) 用@csrf_emption包装您的twilio_响应函数以删除Django csrf令牌检查是正确的方法。Twilio不生成Django CSRF令牌。相反,还有其他验证来自Twilio的帖子的方法,比如使用X-Twilio-signature头进行签名验证。有关详细信息,请参阅
1a)使用GET请求便于测试和调试,但在生产中应使用POST。根据HTTP规范,GET请求没有正文,因此结果在查询字符串中传递。如果参数太大,例如文本消息的最大长度为1600个字符,则URL中的查询字符串可能超过URL的最大长度,并可能在处理字符串时导致问题
2) Django表单是这个用例的一个好方法,尤其是一个利用现有模型保存响应的ModelForm。例如,您的模型表单可以
如果要将数据保存到TwilioMessage模型,请执行以下操作:
from django.forms import ModelForm
from .models import TwilioMessage
class MessageForm(ModelForm):
pass
class Meta:
model = ReactionEvent
# include all fields you're saving from the form here
fields = ['body', 'to', 'from_', 'signature',]
令人惊叹的。感谢您的详细回复!