falcon-autocrud:如何处理唯一行?
falcon-autocrud: how to handle unique rows?
我想用 Falcon 创建一个简单的应用程序,它能够处理带有 hostname
: ip
条记录的小型 sqlite 数据库。我希望能够替换 sqlite 中的行,所以我决定 hostname
是唯一字段。我有一个 model.py
:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String
Base = declarative_base()
DB_URI = 'sqlite:///clients.db'
class Client(Base):
__tablename__ = 'clients'
id = Column(Integer, primary_key=True)
hostname = Column(String(50), unique=True)
ip = Column(String(50))
我的简单resources.py
:
from falcon_autocrud.resource import CollectionResource, SingleResource
from models import *
class ClientCollectionResource(CollectionResource):
model = Client
methods = ['GET', 'POST']
当我使用有关 hostname
的更新信息发出 POST 请求时:ip
我收到 Unique constraint violated
错误:
req = requests.post('http://localhost:8000/clients',
headers={'Content-Type': 'application/json'},
data=json.dumps({'hostname': 'laptop1', 'ip': '192.168.0.33'}));
req.content
>> b'{"title": "Conflict", "description": "Unique constraint violated"}'
有什么方法可以使用 sqlalchemy
替换现有记录吗?或者也许我为这些目的选择了 sqlite 是错误的?
构建 REST-ful API 时,您应该 不 使用 POST
更新现有资源, POST
到资源应该只创建新资源。 falcon-autocrud
在这里做正确的事。
而是对单个资源(为 .../clients/<identifier>
注册的 SingleResource
资源)使用 PUT
来更改现有资源。
如果您在 SingleResource
定义中使用 hostname
,那么 falcon-autocrud
应该自动使用该列作为标识符(假设您的 SingleResource
子类被称为 ClientResource
):
app.add_route('/clients/{hostname}', ClientResource(db_engine))
此时您可以 PUT
新的 ip
值直接使用:
requests.put('http://localhost:8000/clients/laptop1', json={'ip': '192.168.0.33'})
(请注意,requests
直接支持 JSON 请求;json=
关键字参数为您编码为 JSON,而 Content-Type
header是在你使用的时候自动为你设置的)。
您可能想要限制为 Client
objects 返回的字段。使用唯一的 hostname
,您不希望通过同时发送主键列来混淆客户。我会通过在您的资源 类:
上设置 response_fields
属性来限制响应字段
class ClientCollectionResource(CollectionResource):
model = Client
response_fields = ['hostname', 'ip']
methods = ['GET', 'POST']
class ClientResource(SingleResource):
model = Client
response_fields = ['hostname', 'ip']
我看到 falcon-autocrud
尚不支持 collection 上更改现有资源的 PATCH
请求(仅支持 "op": "add"
),否则也是更改现有条目的另一条途径。
我想用 Falcon 创建一个简单的应用程序,它能够处理带有 hostname
: ip
条记录的小型 sqlite 数据库。我希望能够替换 sqlite 中的行,所以我决定 hostname
是唯一字段。我有一个 model.py
:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String
Base = declarative_base()
DB_URI = 'sqlite:///clients.db'
class Client(Base):
__tablename__ = 'clients'
id = Column(Integer, primary_key=True)
hostname = Column(String(50), unique=True)
ip = Column(String(50))
我的简单resources.py
:
from falcon_autocrud.resource import CollectionResource, SingleResource
from models import *
class ClientCollectionResource(CollectionResource):
model = Client
methods = ['GET', 'POST']
当我使用有关 hostname
的更新信息发出 POST 请求时:ip
我收到 Unique constraint violated
错误:
req = requests.post('http://localhost:8000/clients',
headers={'Content-Type': 'application/json'},
data=json.dumps({'hostname': 'laptop1', 'ip': '192.168.0.33'}));
req.content
>> b'{"title": "Conflict", "description": "Unique constraint violated"}'
有什么方法可以使用 sqlalchemy
替换现有记录吗?或者也许我为这些目的选择了 sqlite 是错误的?
构建 REST-ful API 时,您应该 不 使用 POST
更新现有资源, POST
到资源应该只创建新资源。 falcon-autocrud
在这里做正确的事。
而是对单个资源(为 .../clients/<identifier>
注册的 SingleResource
资源)使用 PUT
来更改现有资源。
如果您在 SingleResource
定义中使用 hostname
,那么 falcon-autocrud
应该自动使用该列作为标识符(假设您的 SingleResource
子类被称为 ClientResource
):
app.add_route('/clients/{hostname}', ClientResource(db_engine))
此时您可以 PUT
新的 ip
值直接使用:
requests.put('http://localhost:8000/clients/laptop1', json={'ip': '192.168.0.33'})
(请注意,requests
直接支持 JSON 请求;json=
关键字参数为您编码为 JSON,而 Content-Type
header是在你使用的时候自动为你设置的)。
您可能想要限制为 Client
objects 返回的字段。使用唯一的 hostname
,您不希望通过同时发送主键列来混淆客户。我会通过在您的资源 类:
response_fields
属性来限制响应字段
class ClientCollectionResource(CollectionResource):
model = Client
response_fields = ['hostname', 'ip']
methods = ['GET', 'POST']
class ClientResource(SingleResource):
model = Client
response_fields = ['hostname', 'ip']
我看到 falcon-autocrud
尚不支持 collection 上更改现有资源的 PATCH
请求(仅支持 "op": "add"
),否则也是更改现有条目的另一条途径。