2

我正在使用couchdb-python来访问我的 CouchDB 后端。有时我想知道库正在访问的 URL,以便使用curl或任何其他工具访问完全相同的 URL。也就是说,我希望能够复制/粘贴编码的 URL 并执行 curl 访问,而无需手动编辑任何内容

由于couchdb-python没有给我这些信息,我构建了一个小工具来获取 URL:

import urllib

def get_couchdb_url(server, database, design_doc, view_name, **options):
    prefix = 'http://%s:%d' % (server, 5984)
    url = '/'.join([prefix, database, "_design", design_doc, '_view', view_name])
    params = urllib.urlencode(options)
    if params != "" : url += "?" + params
    return url

number='+666666666'
print get_couchdb_url('localhost', 'phonenumbers', 'control', 'allgeonums', key = number)

这给了我以下网址:

http://localhost:5984/phonenumbers/_design/control/_view/allgeonums?key=%2B666666666

如果我使用 curl 访问,它会给出:

curl -X GET 'http://localhost:5984/phonenumbers/_design/control/_view/allgeonums?key=%2B666666666'
{"error":"bad_request","reason":"invalid_json"}

如果我手动编辑 URL,在键值之前和之后添加 %22,CouchDB 会接受它并给我正确的答案:

curl -X GET 'http://localhost:5984/phonenumbers/_design/control/_view/allgeonums?key=%22%2B666666666%22'

现在我有两个问题:

  • Can couchdb-python show me the URL it is accessing?
  • How can I tell urllib.urlencode to produce encoded data which can be accepted by CouchDB? According to the manual, the values must be url encoded. I am not sure how to do this, for the general case. I would like to avoid having to read the couchdb-python sources for just this simple problem.
4

2 回答 2

1

Sure it could and pretty simple, but using some internals:

import couchdb
from couchdb.http import urljoin
from couchdb.client import _encode_view_options
server = couchdb.Server()
db = server['blog']
res = db.view('posts/by_author', key='Mike', reduce=False, include_docs=True)
print urljoin(res.view.resource.url, **_encode_view_options(res.options))

Will give you output:

http://localhost:5984/blog/_design/posts/_view/by_author?key=%22Mike%22&reduce=false&include_docs=true

_encode_view_options the only need to enforce JSON value for key, startkey and endkey parameters and encode in same way any non string ones. You may just implement this function by yourself if import private functions is unavailable for some reasons.

于 2012-11-27T20:02:52.123 回答
0

It seems the values in the query options must be first converted to json, and then they can be url-encoded. I have come up with the following code:

import simplejson as json
import urllib

def json_encode_options(**options):
    json_options = { }
    for k, v in options.iteritems():
        v_encoded = json.dumps(v)
        json_options[k] = v_encoded
    return urllib.urlencode(json_options)

def get_couchdb_url(server, database, design_doc, view_name, **options):
    prefix = 'http://%s:%d' % (server, 5984)
    url = '/'.join([prefix, database, "_design", design_doc, '_view', view_name])
    params = json_encode_options(**options)
    if params != "" : url += "?" + params
    return url

number='+666666666'
print get_couchdb_url('localhost', 'phonenumbers', 'control', 'allgeonums', key = number)
于 2012-11-27T21:06:41.980 回答