处理自定义ID字段¶
当涉及到单个文档端点时,在大多数情况下,除了定义父资源端点之外,您没有任何事情可做。所以假设您配置了 /invoices
端点,这将允许客户端查询基础 invoices 数据库集合。这个 /invoices/<ObjectId>
端点将由框架提供,客户端将使用端点来检索和/或编辑单个文档。默认情况下,当 ID_FIELD
字段属于 ObjectId
类型。
但是,您可能有一些集合,其中唯一标识符不是 ObjectId
,您仍然希望单个文档端点正常工作。别担心,这是可行的,只需要稍加修补。
处理 UUID
领域¶
在本教程中,我们将考虑一个场景,其中一个数据库集合(发票)使用UUID字段作为唯一标识符。我们希望我们的API公开一个文档端点,比如 /invoices/uuid
,意思是:
/invoices/48c00ee9-4dbe-413f-9fc3-d5f12a91de1c
.
我们需要遵循以下步骤:
创建一个定制的JSonencoder,它能够将UUID序列化为字符串,并将其传递给我们的EVE应用程序。
添加新的支持
uuid
数据类型,以便正确验证传入的UUID值。配置我们的发票端点,以便EVE知道如何正确解析UUID URL。
自定义JSonencoder¶
EVE默认的JSON序列化程序完全能够序列化像 datetime
(序列化为rfc1123字符串,如 Sat, 23 Feb 1985 12:00:00 GMT
) ObjectId
值(也序列化为字符串)。
由于我们正在添加对未知数据类型的支持,因此还需要指示EVE实例如何正确序列化它。这就像对标准进行子类化一样简单。 JSONEncoder
或者,更好的是,Eve自己的 BaseJSONEncoder
,因此我们的自定义序列化程序将保留EVE的所有序列化魔力:
from eve.io.base import BaseJSONEncoder
from uuid import UUID
class UUIDEncoder(BaseJSONEncoder):
""" JSONEconder subclass used by the json render function.
This is different from BaseJSONEoncoder since it also addresses
encoding of UUID
"""
def default(self, obj):
if isinstance(obj, UUID):
return str(obj)
else:
# delegate rendering to base class method (the base class
# will properly render ObjectIds, datetimes, etc.)
return super(UUIDEncoder, self).default(obj)
UUID
验证¶
默认情况下,EVE为每个新插入的文档创建一个唯一的标识符,即 ObjectId
类型。这不是我们希望在这个端点发生的事情。在这里,我们希望客户机本身提供唯一的标识符,并且还希望验证它们是UUID类型。为了实现这一点,我们首先需要扩展数据验证层(请参见 数据验证 有关自定义验证的详细信息:
from eve.io.mongo import Validator
from uuid import UUID
class UUIDValidator(Validator):
"""
Extends the base mongo validator adding support for the uuid data-type
"""
def _validate_type_uuid(self, value):
try:
UUID(value)
return True
except ValueError:
pass
UUID
URLs¶
现在EVE能够呈现和验证UUID值,但它仍然不知道哪些资源将使用这些特性。我们还需要设置 item_url
因此,可以正确解析UUID格式的URL。让我们选择我们的 settings.py
模块化并相应地更新API域:
invoices = {
# this resource item endpoint (/invoices/<id>) will match a UUID regex.
'item_url': 'regex("[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}")',
'schema': {
# set our _id field of our custom uuid type.
'_id': {'type': 'uuid'},
},
}
DOMAIN = {
'invoices': invoices
}
如果您的所有API资源都将支持UUID作为唯一的文档标识符,那么您可能只需要设置全局 ITEM_URL
为了避免为每个资源端点设置UUID regex。
路过 UUID
Eve的果汁¶
现在所有丢失的部分都在那里了,我们只需要指导Eve如何使用它们。EVE在构建URL映射时需要了解新的数据类型,因此我们需要在开始时传递自定义类,当我们正在实例化应用程序时:
app = Eve(json_encoder=UUIDEncoder, validator=UUIDValidator)
记住,如果使用自定义 ID_FIELD
然后,您不应该依赖mongodb(和eve)来自动生成 ID_FIELD
为你。你应该传递这个值,就像这样:
POST
{"name":"bill", "_id":"48c00ee9-4dbe-413f-9fc3-d5f12a91de1c"}
备注
默认情况下,Eve将PyMongo的 UuidRepresentation
至 standard
。这允许无缝处理现代的由Python生成的UUID值。您可以通过设置 uuidRepresentation
的价值 MONGO_OPTIONS
如你所愿。有关详细信息,请参阅 PyMongo documentation 。