标签归档:web-services

创建简单的python网络服务的最佳方法

问题:创建简单的python网络服务的最佳方法

我已经使用python多年了,但是我对python Web编程的经验很少。我想创建一个非常简单的Web服务,该服务公开来自现有python脚本的一些功能以供公司使用。它可能会在csv中返回结果。什么是最快的方法?如果它影响您的建议,那么我很可能会在此之后添加更多功能。

I’ve been using python for years, but I have little experience with python web programming. I’d like to create a very simple web service that exposes some functionality from an existing python script for use within my company. It will likely return the results in csv. What’s the quickest way to get something up? If it affects your suggestion, I will likely be adding more functionality to this, down the road.


回答 0

看看werkzeug。Werkzeug最初是WSGI应用程序各种实用程序的简单集合,现已成为最高级的WSGI实用程序模块之一。它包括功能强大的调试器,功能齐全的请求和响应对象,用于处理实体标签的HTTP实用程序,高速缓存控制标头,HTTP日期,cookie处理,文件上传,功能强大的URL路由系统和一堆由社区提供的附加模块。

它包括许多可与http配合使用的出色工具,并且具有可以在不同环境(cgi,fcgi,apache / mod_wsgi或用于调试的普通简单python服务器)中与wsgi一起使用的优点。

Have a look at werkzeug. Werkzeug started as a simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility modules. It includes a powerful debugger, full featured request and response objects, HTTP utilities to handle entity tags, cache control headers, HTTP dates, cookie handling, file uploads, a powerful URL routing system and a bunch of community contributed addon modules.

It includes lots of cool tools to work with http and has the advantage that you can use it with wsgi in different environments (cgi, fcgi, apache/mod_wsgi or with a plain simple python server for debugging).


回答 1

web.py可能是最简单的Web框架。“裸” CGI比较简单,但是在提供一项实际上可以做某事的服务时,您完全是一个人。

“你好,世界!” 根据web.py是不是比裸CGI版本更长的时间,但它增加了URL映射,HTTP命令的区别,和查询参数解析为免费

import web

urls = (
    '/(.*)', 'hello'
)
app = web.application(urls, globals())

class hello:        
    def GET(self, name):
        if not name: 
            name = 'world'
        return 'Hello, ' + name + '!'

if __name__ == "__main__":
    app.run()

web.py is probably the simplest web framework out there. “Bare” CGI is simpler, but you’re completely on your own when it comes to making a service that actually does something.

“Hello, World!” according to web.py isn’t much longer than an bare CGI version, but it adds URL mapping, HTTP command distinction, and query parameter parsing for free:

import web

urls = (
    '/(.*)', 'hello'
)
app = web.application(urls, globals())

class hello:        
    def GET(self, name):
        if not name: 
            name = 'world'
        return 'Hello, ' + name + '!'

if __name__ == "__main__":
    app.run()

回答 2

在线获取Python脚本的最简单方法是使用CGI:

#!/usr/bin/python

print "Content-type: text/html"
print

print "<p>Hello world.</p>"

将该代码放入驻留在Web服务器CGI目录中的脚本中,使其可执行并运行。cgi当您需要接受用户的参数时,该模块具有许多有用的实用程序。

The simplest way to get a Python script online is to use CGI:

#!/usr/bin/python

print "Content-type: text/html"
print

print "<p>Hello world.</p>"

Put that code in a script that lives in your web server CGI directory, make it executable, and run it. The cgi module has a number of useful utilities when you need to accept parameters from the user.


回答 3

原始CGI有点痛苦,Django有点重量级。关于它,有许多更简单,更轻便的框架,例如CherryPy。值得一看。

Raw CGI is kind of a pain, Django is kind of heavyweight. There are a number of simpler, lighter frameworks about, e.g. CherryPy. It’s worth looking around a bit.


回答 4

看一下WSGI参考实现。您已经在Python库中拥有它。这很简单。

Look at the WSGI reference implementation. You already have it in your Python libraries. It’s quite simple.


回答 5

如果您指的是“ Web服务”,则其他程序SimpleXMLRPCServer可能访问了某些 适合您的东西。自版本2.2起,所有Python安装中均包含该功能。

对于简单的人类可访问的东西,我通常使用Python的SimpleHTTPServer,它也随每次安装一起提供。显然,您还可以通过客户端程序访问SimpleHTTPServer。

If you mean with “Web Service” something accessed by other Programms SimpleXMLRPCServer might be right for you. It is included with every Python install since Version 2.2.

For Simple human accessible things I usually use Pythons SimpleHTTPServer which also comes with every install. Obviously you also could access SimpleHTTPServer by client programs.


回答 6

如果您拥有一个好的Web框架,生活将会很简单。Django中的Web服务很简单。定义模型,编写返回CSV文档的视图函数。跳过模板。

Life is simple if you get a good web framework. Web services in Django are easy. Define your model, write view functions that return your CSV documents. Skip the templates.


回答 7

如果您用SOAP / WSDL表示“ Web服务”,则可能需要看一下 使用Python和SOAPpy生成WSDL

If you mean “web service” in SOAP/WSDL sense, you might want to look at Generating a WSDL using Python and SOAPpy


回答 8

也许是扭曲的 http://twistedmatrix.com/trac/


如何在Python中使用WSDL(SOAP)Web服务?

问题:如何在Python中使用WSDL(SOAP)Web服务?

我想在Python中使用基于WSDL SOAP的Web服务。我看过Dive Into Python代码,但是SOAPpy模块在Python 2.5下不起作用。

我已经尝试使用肥皂水(:类型未找到:“项目” suds.TypeNotFound),这部分工作,但打破了某些类型。

我也查看了Client,但这似乎不支持WSDL。

我看过ZSI,但它看起来非常复杂。有人有任何示例代码吗?

WSDL是https://ws.pingdom.com/soap/PingdomAPI.wsdl,可与PHP 5 SOAP客户端配合使用。

I want to use a WSDL SOAP based web service in Python. I have looked at the Dive Into Python code but the SOAPpy module does not work under Python 2.5.

I have tried using suds which works partly, but breaks with certain types (suds.TypeNotFound: Type not found: ‘item’).

I have also looked at Client but this does not appear to support WSDL.

And I have looked at ZSI but it looks very complex. Does anyone have any sample code for it?

The WSDL is https://ws.pingdom.com/soap/PingdomAPI.wsdl and works fine with the PHP 5 SOAP client.


回答 0

我建议您看看SUDS

“ Suds是用于使用Web服务的轻量级SOAP python客户端。”

I would recommend that you have a look at SUDS

“Suds is a lightweight SOAP python client for consuming Web Services.”


回答 1

有一个相对较新的库,它很有前途,尽管文档仍然很少,但看起来很干净并且是pythonic的python zeep

另请参见此答案的示例。

There is a relatively new library which is very promising and albeit still poorly documented, seems very clean and pythonic: python zeep.

See also this answer for an example.


回答 2

我最近偶然发现了同样的问题。这是我的解决方案的摘要:

所需的基本组成代码块

以下是客户端应用程序所需的基本代码块

  1. 会话请求部分:请求与提供者进行会话
  2. 会话认证部分:向提供者提供凭据
  3. 客户端部分:创建客户端
  4. 安全标题部分:将WS-Security标头添加到客户端
  5. 消耗部分:根据需要消耗可用的操作(或方法)

您需要什么模块?

许多建议使用Python模块,例如urllib2;但是,这些模块都不起作用-至少对于该特定项目不起作用。

因此,这是您需要获取的模块列表。首先,您需要从以下链接下载并安装最新版本的suds:

pypi.python.org/pypi/suds-jurko/0.4.1.jurko.2

此外,您需要分别从以下链接下载和安装请求和suds_requests模块(免责声明:我是新来此发布者,因此我现在不能发布多个链接)。

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

一旦成功下载并安装了这些模块,就可以了。

代码

按照前面概述的步骤,代码如下所示:导入:

import logging
from suds.client import Client
from suds.wsse import *
from datetime import timedelta,date,datetime,tzinfo
import requests
from requests.auth import HTTPBasicAuth
import suds_requests

会话请求和身份验证:

username=input('Username:')
password=input('password:')
session = requests.session()
session.auth=(username, password)

创建客户端:

client = Client(WSDL_URL, faults=False, cachingpolicy=1, location=WSDL_URL, transport=suds_requests.RequestsTransport(session))

添加WS-Security标头:

...
addSecurityHeader(client,username,password)
....

def addSecurityHeader(client,username,password):
    security=Security()
    userNameToken=UsernameToken(username,password)
    timeStampToken=Timestamp(validity=600)
    security.tokens.append(userNameToken)
    security.tokens.append(timeStampToken)
    client.set_options(wsse=security)

请注意,此方法将创建图1所示的安全标头。因此,您的实现可能会有所不同,具体取决于所使用服务的所有者提供的正确安全标头格式。

消耗相关的方法(或操作):

result=client.service.methodName(Inputs)

正在记录

在这种实现中的最佳实践之一是记录日志,以查看通信是如何执行的。万一有问题,它使调试变得容易。以下代码进行基本日志记录。但是,除了代码中描述的内容外,您还可以记录通信的许多方面。

logging.basicConfig(level=logging.INFO) 
logging.getLogger('suds.client').setLevel(logging.DEBUG) 
logging.getLogger('suds.transport').setLevel(logging.DEBUG)

结果:

这是我的情况的结果。请注意,服务器返回了HTTP200。这是HTTP请求响应的标准成功代码。

(200, (collectionNodeLmp){
   timestamp = 2014-12-03 00:00:00-05:00
   nodeLmp[] = 
      (nodeLmp){
         pnodeId = 35010357
         name = "YADKIN"
         mccValue = -0.19
         mlcValue = -0.13
         price = 36.46
         type = "500 KV"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
      (nodeLmp){
         pnodeId = 33138769
         name = "ZION 1"
         mccValue = -0.18
         mlcValue = -1.86
         price = 34.75
         type = "Aggregate"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
 })

I recently stumbled up on the same problem. Here is the synopsis of my solution:

Basic constituent code blocks needed

The following are the required basic code blocks of your client application

  1. Session request section: request a session with the provider
  2. Session authentication section: provide credentials to the provider
  3. Client section: create the Client
  4. Security Header section: add the WS-Security Header to the Client
  5. Consumption section: consume available operations (or methods) as needed

What modules do you need?

Many suggested to use Python modules such as urllib2 ; however, none of the modules work-at least for this particular project.

So, here is the list of the modules you need to get. First of all, you need to download and install the latest version of suds from the following link:

pypi.python.org/pypi/suds-jurko/0.4.1.jurko.2

Additionally, you need to download and install requests and suds_requests modules from the following links respectively ( disclaimer: I am new to post in here, so I can’t post more than one link for now).

pypi.python.org/pypi/requests

pypi.python.org/pypi/suds_requests/0.1

Once you successfully download and install these modules, you are good to go.

The code

Following the steps outlined earlier, the code looks like the following: Imports:

import logging
from suds.client import Client
from suds.wsse import *
from datetime import timedelta,date,datetime,tzinfo
import requests
from requests.auth import HTTPBasicAuth
import suds_requests

Session request and authentication:

username=input('Username:')
password=input('password:')
session = requests.session()
session.auth=(username, password)

Create the Client:

client = Client(WSDL_URL, faults=False, cachingpolicy=1, location=WSDL_URL, transport=suds_requests.RequestsTransport(session))

Add WS-Security Header:

...
addSecurityHeader(client,username,password)
....

def addSecurityHeader(client,username,password):
    security=Security()
    userNameToken=UsernameToken(username,password)
    timeStampToken=Timestamp(validity=600)
    security.tokens.append(userNameToken)
    security.tokens.append(timeStampToken)
    client.set_options(wsse=security)

Please note that this method creates the security header depicted in Fig.1. So, your implementation may vary depending on the correct security header format provided by the owner of the service you are consuming.

Consume the relevant method (or operation) :

result=client.service.methodName(Inputs)

Logging:

One of the best practices in such implementations as this one is logging to see how the communication is executed. In case there is some issue, it makes debugging easy. The following code does basic logging. However, you can log many aspects of the communication in addition to the ones depicted in the code.

logging.basicConfig(level=logging.INFO) 
logging.getLogger('suds.client').setLevel(logging.DEBUG) 
logging.getLogger('suds.transport').setLevel(logging.DEBUG)

Result:

Here is the result in my case. Note that the server returned HTTP 200. This is the standard success code for HTTP request-response.

(200, (collectionNodeLmp){
   timestamp = 2014-12-03 00:00:00-05:00
   nodeLmp[] = 
      (nodeLmp){
         pnodeId = 35010357
         name = "YADKIN"
         mccValue = -0.19
         mlcValue = -0.13
         price = 36.46
         type = "500 KV"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
      (nodeLmp){
         pnodeId = 33138769
         name = "ZION 1"
         mccValue = -0.18
         mlcValue = -1.86
         price = 34.75
         type = "Aggregate"
         timestamp = 2014-12-03 01:00:00-05:00
         errorCodeId = 0
      },
 })

回答 3

现在(截止到2008年),所有可用于Python的SOAP库都非常烂。我建议尽可能避免使用SOAP。上次我们被迫使用Python中的SOAP Web服务时,我们用C#编写了一个包装器,该包装器一方面处理SOAP,另一方面则使COM退出。

Right now (as of 2008), all the SOAP libraries available for Python suck. I recommend avoiding SOAP if possible. The last time we where forced to use a SOAP web service from Python, we wrote a wrapper in C# that handled the SOAP on one side and spoke COM out the other.


回答 4

Zeep是一个适合Python的不错的SOAP库,它可以满足您的要求:http : //docs.python-zeep.org

Zeep is a decent SOAP library for Python that matches what you’re asking for: http://docs.python-zeep.org


回答 5

我定期寻找一个令人满意的答案,但是到目前为止还没有运气。我使用soapUI +请求+体力劳动。

我上次要这样做时放弃并使用了Java ,而上次我这样做时仅放弃了几次,但这并不是必需的。

去年在Project Place的RESTful API中成功使用了请求库之后,我想到也许我可以以类似的方式手动滚动要发送的SOAP请求。

事实证明,这并不是很困难,但是这耗时且容易出错,尤其是如果字段名称不一致(我当前正在使用的字段具有“ jobId”,“ JobId”和“ JobID”。我使用soapUI加载) WSDL,以便更轻松地提取端点等并执行一些手动测试。到目前为止,我很幸运没有受到我正在使用的任何WSDL更改的影响。

I periodically search for a satisfactory answer to this, but no luck so far. I use soapUI + requests + manual labour.

I gave up and used Java the last time I needed to do this, and simply gave up a few times the last time I wanted to do this, but it wasn’t essential.

Having successfully used the requests library last year with Project Place’s RESTful API, it occurred to me that maybe I could just hand-roll the SOAP requests I want to send in a similar way.

Turns out that’s not too difficult, but it is time consuming and prone to error, especially if fields are inconsistently named (the one I’m currently working on today has ‘jobId’, JobId’ and ‘JobID’. I use soapUI to load the WSDL to make it easier to extract endpoints etc and perform some manual testing. So far I’ve been lucky not to have been affected by changes to any WSDL that I’m using.


回答 6

并非如此,SOAPpy不适用于Python 2.5-它可以工作,尽管它非常简单,而且确实非常基础。如果您想与任何更复杂的Web服务进行对话,则ZSI是您唯一的朋友。

我发现的真正有用的演示位于http://www.ebi.ac.uk/Tools/webservices/tutorials/python-这确实帮助我了解了ZSI的工作原理。

It’s not true SOAPpy does not work with Python 2.5 – it works, although it’s very simple and really, really basic. If you want to talk to any more complicated webservice, ZSI is your only friend.

The really useful demo I found is at http://www.ebi.ac.uk/Tools/webservices/tutorials/python – this really helped me to understand how ZSI works.


回答 7

如果您要自己动手,则强烈建议您访问http://effbot.org/zone/element-soap.htm

If you’re rolling your own I’d highly recommend looking at http://effbot.org/zone/element-soap.htm.


回答 8

SOAPpy现在已过时,已经被ZSL取代了AFAIK。这是有争议的,因为在Python 2.5或Python 2.6上我都无法工作,更不用说编译了。

SOAPpy is now obsolete, AFAIK, replaced by ZSL. It’s a moot point, because I can’t get either one to work, much less compile, on either Python 2.5 or Python 2.6


回答 9

#!/usr/bin/python
# -*- coding: utf-8 -*-
# consume_wsdl_soap_ws_pss.py
import logging.config
from pysimplesoap.client import SoapClient

logging.config.dictConfig({
    'version': 1,
    'formatters': {
        'verbose': {
            'format': '%(name)s: %(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'pysimplesoap.helpers': {
            'level': 'DEBUG',
            'propagate': True,
            'handlers': ['console'],
        },
    }
})

WSDL_URL = 'http://www.webservicex.net/stockquote.asmx?WSDL'
client = SoapClient(wsdl=WSDL_URL, ns="web", trace=True)
client['AuthHeaderElement'] = {'username': 'someone', 'password': 'nottelling'}

#Discover operations
list_of_services = [service for service in client.services]
print(list_of_services)

#Discover params
method = client.services['StockQuote']

response = client.GetQuote(symbol='GOOG')
print('GetQuote: {}'.format(response['GetQuoteResult']))
#!/usr/bin/python
# -*- coding: utf-8 -*-
# consume_wsdl_soap_ws_pss.py
import logging.config
from pysimplesoap.client import SoapClient

logging.config.dictConfig({
    'version': 1,
    'formatters': {
        'verbose': {
            'format': '%(name)s: %(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'pysimplesoap.helpers': {
            'level': 'DEBUG',
            'propagate': True,
            'handlers': ['console'],
        },
    }
})

WSDL_URL = 'http://www.webservicex.net/stockquote.asmx?WSDL'
client = SoapClient(wsdl=WSDL_URL, ns="web", trace=True)
client['AuthHeaderElement'] = {'username': 'someone', 'password': 'nottelling'}

#Discover operations
list_of_services = [service for service in client.services]
print(list_of_services)

#Discover params
method = client.services['StockQuote']

response = client.GetQuote(symbol='GOOG')
print('GetQuote: {}'.format(response['GetQuoteResult']))

用于测试soap客户端的公共免费Web服务[关闭]

问题:用于测试soap客户端的公共免费Web服务[关闭]

是否有任何公开可用的SOAP 1.2 / WSDL 2.0兼容的免费Web服务用于测试基于Python的soap客户端库(例如Zolera SOAP Infrastructure)?

到目前为止,在我看来,Google Web API可能是唯一的选择。

否则,如何测试符合SOAP 1.2的客户端库?

Are there any publicly available SOAP 1.2/WSDL 2.0 compliant free web services for testing a Python based soap client library (e.g. Zolera SOAP Infrastructure)?

So far, it appears to me that Google Web API may be the only option.

Otherwise, how can one test a SOAP 1.2 compliant client library?


回答 0

这里有一堆:

http://www.webservicex.net/WS/wscatlist.aspx

只需在Google上搜索“免费WebService”或“开放WebService”,您就会发现大量的开放SOAP端点。

记住,可以通过在URL中添加?WSDL来从任何ASMX端点获取WSDL。

There is a bunch on here:

http://www.webservicex.net/WS/wscatlist.aspx

Just google for “Free WebService” or “Open WebService” and you’ll find tons of open SOAP endpoints.

Remember, you can get a WSDL from any ASMX endpoint by adding ?WSDL to the url.


对Python REST(Web服务)框架的建议?[关闭]

问题:对Python REST(Web服务)框架的建议?[关闭]

在服务器端使用这些基于Python的不同REST框架的建议列表中是否可以编写自己的RESTful API?最好有优点和缺点。

请随时在此处添加建议。:)

Is there a list somewhere of recommendations of different Python-based REST frameworks for use on the serverside to write your own RESTful APIs? Preferably with pros and cons.

Please feel free to add recommendations here. :)


回答 0

设计RESTful API时要注意的一点是GET和POST的合并,就好像它们是同一件事一样。使用Django基于函数的视图CherryPy的默认分派器很容易犯此错误,尽管这两个框架现在都提供了解决此问题的方法(分别基于类的视图MethodDispatcher)。

HTTP谓词在REST 中非常重要,除非对此特别小心,否则最终会陷入REST反模式

一些正确的框架是web.pyFlaskBottle。当与mimerender库结合使用时(充分披露:我写了它),它们使您可以编写漂亮的RESTful Web服务:

import web
import json
from mimerender import mimerender

render_xml = lambda message: '<message>%s</message>'%message
render_json = lambda **args: json.dumps(args)
render_html = lambda message: '<html><body>%s</body></html>'%message
render_txt = lambda message: message

urls = (
    '/(.*)', 'greet'
)
app = web.application(urls, globals())

class greet:
    @mimerender(
        default = 'html',
        html = render_html,
        xml  = render_xml,
        json = render_json,
        txt  = render_txt
    )
    def GET(self, name):
        if not name: 
            name = 'world'
        return {'message': 'Hello, ' + name + '!'}

if __name__ == "__main__":
    app.run()

该服务的逻辑仅实现一次,并且正确的表示选择(Accept标头)+分配给正确的呈现函数(或模板)的操作是整齐,透明的。

$ curl localhost:8080/x
<html><body>Hello, x!</body></html>

$ curl -H "Accept: application/html" localhost:8080/x
<html><body>Hello, x!</body></html>

$ curl -H "Accept: application/xml" localhost:8080/x
<message>Hello, x!</message>

$ curl -H "Accept: application/json" localhost:8080/x
{'message':'Hello, x!'}

$ curl -H "Accept: text/plain" localhost:8080/x
Hello, x!

更新(2012年4月):添加了有关Django基于类的视图,CherryPy的MethodDispatcher和Flask and Bottle框架的信息。提出问题时,两者都不存在。

Something to be careful about when designing a RESTful API is the conflation of GET and POST, as if they were the same thing. It’s easy to make this mistake with Django‘s function-based views and CherryPy‘s default dispatcher, although both frameworks now provide a way around this problem (class-based views and MethodDispatcher, respectively).

HTTP-verbs are very important in REST, and unless you’re very careful about this, you’ll end up falling into a REST anti-pattern.

Some frameworks that get it right are web.py, Flask and Bottle. When combined with the mimerender library (full disclosure: I wrote it), they allow you to write nice RESTful webservices:

import web
import json
from mimerender import mimerender

render_xml = lambda message: '<message>%s</message>'%message
render_json = lambda **args: json.dumps(args)
render_html = lambda message: '<html><body>%s</body></html>'%message
render_txt = lambda message: message

urls = (
    '/(.*)', 'greet'
)
app = web.application(urls, globals())

class greet:
    @mimerender(
        default = 'html',
        html = render_html,
        xml  = render_xml,
        json = render_json,
        txt  = render_txt
    )
    def GET(self, name):
        if not name: 
            name = 'world'
        return {'message': 'Hello, ' + name + '!'}

if __name__ == "__main__":
    app.run()

The service’s logic is implemented only once, and the correct representation selection (Accept header) + dispatch to the proper render function (or template) is done in a tidy, transparent way.

$ curl localhost:8080/x
<html><body>Hello, x!</body></html>

$ curl -H "Accept: application/html" localhost:8080/x
<html><body>Hello, x!</body></html>

$ curl -H "Accept: application/xml" localhost:8080/x
<message>Hello, x!</message>

$ curl -H "Accept: application/json" localhost:8080/x
{'message':'Hello, x!'}

$ curl -H "Accept: text/plain" localhost:8080/x
Hello, x!

Update (April 2012): added information about Django’s class-based views, CherryPy’s MethodDispatcher and Flask and Bottle frameworks. Neither existed back when the question was asked.


回答 1

没人惊讶烧瓶

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

Surprised no one mentioned flask.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

回答 2

我们正在将Django用于RESTful Web服务。

请注意,开箱即用的Django没有满足我们需求的足够细粒度的身份验证。我们使用了Django-REST接口,它帮了很多忙。[我们已经推出了自己的产品,因为我们进行了太多扩展,已经成为维护的噩梦。]

我们有两种URL:实现面向人的HTML页面的“ html” URL和实现面向Web服务的处理的“ json” URL。我们的视图功能通常看起来像这样。

def someUsefulThing( request, object_id ):
    # do some processing
    return { a dictionary with results }

def htmlView( request, object_id ):
    d = someUsefulThing( request, object_id )
    render_to_response( 'template.html', d, ... )

def jsonView( request, object_id ):
    d = someUsefulThing( request, object_id )
    data = serializers.serialize( 'json', d['object'], fields=EXPOSED_FIELDS )
    response = HttpResponse( data, status=200, content_type='application/json' )
    response['Location']= reverse( 'some.path.to.this.view', kwargs={...} )
    return response

关键是有用的功能是从两个演示中排除的。JSON表示形式通常只是所请求的一个对象。HTML演示文稿通常包括各种导航辅助工具和其他有助于人们提高工作效率的上下文提示。

这些jsonView功能都非常相似,可能有点烦人。但这是Python,因此请使其成为可调用类的一部分,或者在有帮助的情况下编写装饰器。

We’re using Django for RESTful web services.

Note that — out of the box — Django did not have fine-grained enough authentication for our needs. We used the Django-REST interface, which helped a lot. [We’ve since rolled our own because we’d made so many extensions that it had become a maintenance nightmare.]

We have two kinds of URL’s: “html” URL’s which implement the human-oriented HTML pages, and “json” URL’s which implement the web-services oriented processing. Our view functions often look like this.

def someUsefulThing( request, object_id ):
    # do some processing
    return { a dictionary with results }

def htmlView( request, object_id ):
    d = someUsefulThing( request, object_id )
    render_to_response( 'template.html', d, ... )

def jsonView( request, object_id ):
    d = someUsefulThing( request, object_id )
    data = serializers.serialize( 'json', d['object'], fields=EXPOSED_FIELDS )
    response = HttpResponse( data, status=200, content_type='application/json' )
    response['Location']= reverse( 'some.path.to.this.view', kwargs={...} )
    return response

The point being that the useful functionality is factored out of the two presentations. The JSON presentation is usually just one object that was requested. The HTML presentation often includes all kinds of navigation aids and other contextual clues that help people be productive.

The jsonView functions are all very similar, which can be a bit annoying. But it’s Python, so make them part of a callable class or write decorators if it helps.


回答 3

请参阅Python Web Frameworks Wiki。

您可能不需要完整的堆栈框架,但是其余列表仍然很长。

See Python Web Frameworks wiki.

You probably do not need the full stack frameworks, but the remaining list is still quite long.


回答 4

我真的很喜欢CherryPy。这是一个宁静的Web服务的示例:

import cherrypy
from cherrypy import expose

class Converter:
    @expose
    def index(self):
        return "Hello World!"

    @expose
    def fahr_to_celc(self, degrees):
        temp = (float(degrees) - 32) * 5 / 9
        return "%.01f" % temp

    @expose
    def celc_to_fahr(self, degrees):
        temp = float(degrees) * 9 / 5 + 32
        return "%.01f" % temp

cherrypy.quickstart(Converter())

这强调了我对CherryPy的真正喜欢;这是一个完全可行的示例,即使对于不了解该框架的人也非常容易理解。如果运行此代码,则可以立即在Web浏览器中看到结果;例如,访问http:// localhost:8080 / celc_to_fahr?degrees = 50将显示122.0在您的Web浏览器中。

I really like CherryPy. Here’s an example of a restful web service:

import cherrypy
from cherrypy import expose

class Converter:
    @expose
    def index(self):
        return "Hello World!"

    @expose
    def fahr_to_celc(self, degrees):
        temp = (float(degrees) - 32) * 5 / 9
        return "%.01f" % temp

    @expose
    def celc_to_fahr(self, degrees):
        temp = float(degrees) * 9 / 5 + 32
        return "%.01f" % temp

cherrypy.quickstart(Converter())

This emphasizes what I really like about CherryPy; this is a completely working example that’s very understandable even to someone who doesn’t know the framework. If you run this code, then you can immediately see the results in your web browser; e.g. visiting http://localhost:8080/celc_to_fahr?degrees=50 will display 122.0 in your web browser.


回答 5


回答 6

我看不出有任何理由使用Django来公开REST api,有更轻便,更灵活的解决方案。Django将很多其他东西带到了表中,这些东西并非总是需要的。如果您只想将某些代码公开为REST服务,则可以肯定不需要。

我的个人经验是,一旦有了一个千篇一律的框架,您就会开始使用它的ORM,其插件等,只是因为它很容易,而且在任何时候您都最终没有依赖关系这很难摆脱。

选择一个Web框架是一个艰难的决定,并且我会避免为了展示REST api而选择一个完整的堆栈解决方案。

现在,如果您确实需要/想要使用Django,那么Piston是一个适用于Django应用程序的不错的REST框架。

话虽如此,CherryPy看起来也非常不错,但是看起来比REST更像RPC。

查看示例(我从未使用过),如果您只需要REST,则web.py可能是最好的和最干净的。

I don’t see any reason to use Django just to expose a REST api, there are lighter and more flexible solutions. Django carries a lot of other things to the table, that are not always needed. For sure not needed if you only want to expose some code as a REST service.

My personal experience, fwiw, is that once you have a one-size-fits-all framework, you’ll start to use its ORM, its plugins, etc. just because it’s easy, and in no time you end up having a dependency that is very hard to get rid of.

Choosing a web framework is a tough decision, and I would avoid picking a full stack solution just to expose a REST api.

Now, if you really need/want to use Django, then Piston is a nice REST framework for django apps.

That being said, CherryPy looks really nice too, but seems more RPC than REST.

Looking at the samples (I never used it), probably web.py is the best and cleanest if you only need REST.


回答 7

这是基于REST的CherryPy文档中的讨论:http : //docs.cherrypy.org/dev/progguide/REST.html

特别是提到了一个内置的CherryPy调度程序,称为MethodDispatcher,该调度程序根据其HTTP动词标识符(GET,POST等)调用方法。

Here is a discussion in CherryPy docs on REST: http://docs.cherrypy.org/dev/progguide/REST.html

In particular it mentions a built in CherryPy dispatcher called MethodDispatcher, which invokes methods based on their HTTP-verb identifiers (GET, POST, etc…).


回答 8

在2010年,Pylons和repoze.bfg社区“联合起来”创建了Pyramid,这是一个基于repoze.bfg的网络框架。它保留了其父框架的理念,并且可以用于RESTful服务。值得一看。

In 2010, the Pylons and repoze.bfg communities “joined forces” to create Pyramid, a web framework based most heavily on repoze.bfg. It retains the philosophies of its parent frameworks, and can be used for RESTful services. It’s worth a look.


回答 9

Piston是用于为Django应用程序编写RESTful API的非常灵活的框架。

Piston is very flexible framework for wirting RESTful APIs for Django applications.


回答 10

似乎所有种类的python Web框架现在都可以实现RESTful接口。

对于Django,除了好吃的东西和活塞,django-rest-framework是一个很有前途的值得一提的东西。我已经顺利地迁移了我的一个项目。

Django REST框架是适用于Django的轻量级REST框架,旨在简化构建相互连接,自描述的RESTful Web API的过程。

快速示例:

from django.conf.urls.defaults import patterns, url
from djangorestframework.resources import ModelResource
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from myapp.models import MyModel

class MyResource(ModelResource):
    model = MyModel

urlpatterns = patterns('',
    url(r'^$', ListOrCreateModelView.as_view(resource=MyResource)),
    url(r'^(?P<pk>[^/]+)/$', InstanceModelView.as_view(resource=MyResource)),
)

以官方网站为例,以上所有代码均提供api,自我解释的文档(如基于soap的webservice)甚至沙盒进行测试。非常方便。

链接:http//django-rest-framework.org/

Seems all kinds of python web frameworks can implement RESTful interfaces now.

For Django, besides tastypie and piston, django-rest-framework is a promising one worth to mention. I’ve already migrated one of my project on it smoothly.

Django REST framework is a lightweight REST framework for Django, that aims to make it easy to build well-connected, self-describing RESTful Web APIs.

Quick example:

from django.conf.urls.defaults import patterns, url
from djangorestframework.resources import ModelResource
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from myapp.models import MyModel

class MyResource(ModelResource):
    model = MyModel

urlpatterns = patterns('',
    url(r'^$', ListOrCreateModelView.as_view(resource=MyResource)),
    url(r'^(?P<pk>[^/]+)/$', InstanceModelView.as_view(resource=MyResource)),
)

Take the example from official site, all above codes provide api, self explained document(like soap based webservice) and even sandbox to test a bit. Very convenience.

Links: http://django-rest-framework.org/


回答 11

我不是python世界的专家,但是我一直在使用django,它是一个出色的Web框架,可用于创建一个宁静的框架。

I am not an expert on the python world but I have been using django which is an excellent web framework and can be used to create a restful framework.


回答 12

web2py包括对轻松构建RESTful API的支持,如此此处所述(视频)。特别地,请看一下parse_as_rest,它使您可以定义将请求参数映射到数据库查询的URL模式。和smart_query,使您可以在URL中传递任意自然语言查询。

web2py includes support for easily building RESTful API’s, described here and here (video). In particular, look at parse_as_rest, which lets you define URL patterns that map request args to database queries; and smart_query, which enables you to pass arbitrary natural language queries in the URL.


回答 13

如果您使用的是Django,则可以考虑使用django-tastypie替代django-piston。与活塞相比,调整到非ORM数据源更容易,并且文档丰富。

I you are using Django then you can consider django-tastypie as an alternative to django-piston. It is easier to tune to non-ORM data sources than piston, and has great documentation.


回答 14

我强烈推荐TurboGears或Bottle:

TurboGears:

  • 不如django冗长
  • 更灵活,更少HTML
  • 但是:不太有名

瓶子:

  • 非常快
  • 很容易学习
  • 但是:简约而不成熟

I strongly recommend TurboGears or Bottle:

TurboGears:

  • less verbose than django
  • more flexible, less HTML-oriented
  • but: less famous

Bottle:

  • very fast
  • very easy to learn
  • but: minimalistic and not mature

回答 15

我们正在为严格的REST服务开发框架,请访问http://prestans.googlecode.com。

目前在Alpha早期,我们正在针对mod_wsgi和Google的AppEngine进行测试。

寻找测试人员和反馈。谢谢。

We are working on a framework for strict REST services, check out http://prestans.googlecode.com

Its in early Alpha at the moment, we are testing against mod_wsgi and Google’s AppEngine.

Looking for testers and feedback. Thanks.


如何使用Flask从URL获取命名参数?

问题:如何使用Flask从URL获取命名参数?

当用户访问在我的flask应用程序上运行的URL时,我希望Web服务能够处理问号后指定的参数:

http://10.1.1.1:5000/login?username=alex&password=pw1

#I just want to be able to manipulate the parameters
@app.route('/login', methods=['GET', 'POST'])
def login():
    username = request.form['username']
    print(username)
    password = request.form['password']
    print(password)

When the user accesses this URL running on my flask app, I want the web service to be able to handle the parameters specified after the question mark:

http://10.1.1.1:5000/login?username=alex&password=pw1

#I just want to be able to manipulate the parameters
@app.route('/login', methods=['GET', 'POST'])
def login():
    username = request.form['username']
    print(username)
    password = request.form['password']
    print(password)

回答 0

使用request.args得到解析查询字符串的内容:

from flask import request

@app.route(...)
def login():
    username = request.args.get('username')
    password = request.args.get('password')

Use request.args to get parsed contents of query string:

from flask import request

@app.route(...)
def login():
    username = request.args.get('username')
    password = request.args.get('password')

回答 1

URL参数可在中使用request.args,它是具有方法的ImmutableMultiDict,具有get默认值(default)和类型(type)的可选参数-这是可调用的方法,可将输入值转换为所需的格式。(有关更多详细信息,请参见该方法文档。)

from flask import request

@app.route('/my-route')
def my_route():
  page = request.args.get('page', default = 1, type = int)
  filter = request.args.get('filter', default = '*', type = str)

上面的代码示例:

/my-route?page=34               -> page: 34  filter: '*'
/my-route                       -> page:  1  filter: '*'
/my-route?page=10&filter=test   -> page: 10  filter: 'test'
/my-route?page=10&filter=10     -> page: 10  filter: '10'
/my-route?page=*&filter=*       -> page:  1  filter: '*'

The URL parameters are available in request.args, which is an ImmutableMultiDict that has a get method, with optional parameters for default value (default) and type (type) – which is a callable that converts the input value to the desired format. (See the documentation of the method for more details.)

from flask import request

@app.route('/my-route')
def my_route():
  page = request.args.get('page', default = 1, type = int)
  filter = request.args.get('filter', default = '*', type = str)

Examples with the code above:

/my-route?page=34               -> page: 34  filter: '*'
/my-route                       -> page:  1  filter: '*'
/my-route?page=10&filter=test   -> page: 10  filter: 'test'
/my-route?page=10&filter=10     -> page: 10  filter: '10'
/my-route?page=*&filter=*       -> page:  1  filter: '*'

回答 2

您还可以在视图定义的URL上使用方括号<>,此输入将进入您的视图函数参数

@app.route('/<name>')
def my_view_func(name):
    return name

You can also use brackets <> on the URL of the view definition and this input will go into your view function arguments

@app.route('/<name>')
def my_view_func(name):
    return name

回答 3

如果您在URL中传递了一个参数,则可以按照以下步骤进行操作

from flask import request
#url
http://10.1.1.1:5000/login/alex

from flask import request
@app.route('/login/<username>', methods=['GET'])
def login(username):
    print(username)

如果您有多个参数:

#url
http://10.1.1.1:5000/login?username=alex&password=pw1

from flask import request
@app.route('/login', methods=['GET'])
    def login():
        username = request.args.get('username')
        print(username)
        password= request.args.get('password')
        print(password)

在POST请求的情况下,您尝试执行的操作将参数作为表单参数传递并且不出现在URL中。如果您实际上正在开发登录API,建议您使用POST请求而不是GET,并将数据公开给用户。

如果有职位要求,它将按以下方式工作:

#url
http://10.1.1.1:5000/login

HTML片段:

<form action="http://10.1.1.1:5000/login" method="POST">
  Username : <input type="text" name="username"><br>
  Password : <input type="password" name="password"><br>
  <input type="submit" value="submit">
</form>

路线:

from flask import request
@app.route('/login', methods=['POST'])
    def login():
        username = request.form.get('username')
        print(username)
        password= request.form.get('password')
        print(password)

If you have a single argument passed in the URL you can do it as follows

from flask import request
#url
http://10.1.1.1:5000/login/alex

from flask import request
@app.route('/login/<username>', methods=['GET'])
def login(username):
    print(username)

In case you have multiple parameters:

#url
http://10.1.1.1:5000/login?username=alex&password=pw1

from flask import request
@app.route('/login', methods=['GET'])
    def login():
        username = request.args.get('username')
        print(username)
        password= request.args.get('password')
        print(password)

What you were trying to do works in case of POST requests where parameters are passed as form parameters and do not appear in the URL. In case you are actually developing a login API, it is advisable you use POST request rather than GET and expose the data to the user.

In case of post request, it would work as follows:

#url
http://10.1.1.1:5000/login

HTML snippet:

<form action="http://10.1.1.1:5000/login" method="POST">
  Username : <input type="text" name="username"><br>
  Password : <input type="password" name="password"><br>
  <input type="submit" value="submit">
</form>

Route:

from flask import request
@app.route('/login', methods=['POST'])
    def login():
        username = request.form.get('username')
        print(username)
        password= request.form.get('password')
        print(password)

回答 4

网址:

http://0.0.0.0:5000/user/name/

码:

@app.route('/user/<string:name>/', methods=['GET', 'POST'])
def user_view(name):
    print(name)

(编辑:删除格式字符串中的空格)

url:

http://0.0.0.0:5000/user/name/

code:

@app.route('/user/<string:name>/', methods=['GET', 'POST'])
def user_view(name):
    print(name)

(Edit: removed spaces in format string)


回答 5

真的很简单。让我将此过程分为两个简单步骤。

  1. 在html模板上,您将用户名和密码的名称标签声明为

    <form method="POST">
    <input type="text" name="user_name"></input>
    <input type="text" name="password"></input>
    </form>
  2. 然后,将代码修改为:

    from flask import request
    
    @app.route('/my-route', methods=['POST']) #you should always parse username and 
    # password in a POST method not GET
    def my_route():
      username = request.form.get("user_name")
      print(username)
      password = request.form.get("password")
      print(password)
    #now manipulate the username and password variables as you wish
    #Tip: define another method instead of methods=['GET','POST'], if you want to  
    # render the same template with a GET request too

It’s really simple. Let me divide this process into two simple steps.

  1. On the html template you will declare name tag for username and password as

    <form method="POST">
    <input type="text" name="user_name"></input>
    <input type="text" name="password"></input>
    </form>
    
  2. Then, modify your code as:

    from flask import request
    
    @app.route('/my-route', methods=['POST']) #you should always parse username and 
    # password in a POST method not GET
    def my_route():
      username = request.form.get("user_name")
      print(username)
      password = request.form.get("password")
      print(password)
    #now manipulate the username and password variables as you wish
    #Tip: define another method instead of methods=['GET','POST'], if you want to  
    # render the same template with a GET request too
    

回答 6

使用request.args.get(param),例如:

http://10.1.1.1:5000/login?username=alex&password=pw1
@app.route('/login', methods=['GET', 'POST'])
def login():
    username = request.args.get('username')
    print(username)
    password = request.args.get('password')
    print(password)

这是代码的引用链接。

Use request.args.get(param), for example:

http://10.1.1.1:5000/login?username=alex&password=pw1
@app.route('/login', methods=['GET', 'POST'])
def login():
    username = request.args.get('username')
    print(username)
    password = request.args.get('password')
    print(password)

Here is the referenced link to the code.