Add / remove devices from lots with POST / DELETE

This commit is contained in:
Xavier Bustamante Talavera 2018-09-20 18:25:47 +02:00
parent f56ca473e8
commit 7cfae43c7a
6 changed files with 56 additions and 23 deletions

View File

@ -12,6 +12,7 @@ from ereuse_devicehub.db import db
from ereuse_devicehub.resources.agent.models import Person from ereuse_devicehub.resources.agent.models import Person
from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.event import models as m
from ereuse_devicehub.resources.inventory import Inventory from ereuse_devicehub.resources.inventory import Inventory
from ereuse_devicehub.resources.lot.models import Lot
from ereuse_devicehub.resources.tag.model import Tag from ereuse_devicehub.resources.tag.model import Tag
from ereuse_devicehub.resources.user import User from ereuse_devicehub.resources.user import User
@ -89,11 +90,14 @@ class Dummy:
}, },
res=m.Event) res=m.Event)
from tests.test_lot import test_post_add_children_view, test_post_add_device_view from tests.test_lot import test_post_add_children_view
test_post_add_children_view(user) child_id = test_post_add_children_view(user)
# todo this does not add devices to lots lot, _ = user.post({},
test_post_add_device_view(user) res=Lot,
item='{}/devices'.format(child_id),
query=[('id', pc) for pc in itertools.islice(pcs, len(pcs) // 3)])
assert len(lot['devices'])
print('⭐ Done.') print('⭐ Done.')

View File

@ -26,7 +26,7 @@ class Device(Thing):
height = ... # type: Column height = ... # type: Column
depth = ... # type: Column depth = ... # type: Column
color = ... # type: Column color = ... # type: Column
parents = ... # type: relationship lots = ... # type: relationship
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
@ -47,7 +47,7 @@ class Device(Thing):
self.events_one = ... # type: Set[EventWithOneDevice] self.events_one = ... # type: Set[EventWithOneDevice]
self.images = ... # type: ImageList self.images = ... # type: ImageList
self.tags = ... # type: Set[Tag] self.tags = ... # type: Set[Tag]
self.parents = ... # type: Set[Lot] self.lots = ... # type: Set[Lot]
class DisplayMixin: class DisplayMixin:

View File

@ -20,13 +20,17 @@ class LotDef(Resource):
root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()): root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
super().__init__(app, import_name, static_folder, static_url_path, template_folder, super().__init__(app, import_name, static_folder, static_url_path, template_folder,
url_prefix, subdomain, url_defaults, root_path, cli_commands) url_prefix, subdomain, url_defaults, root_path, cli_commands)
children = LotChildrenView.as_view('lot-children', definition=self, auth=app.auth) lot_children = LotChildrenView.as_view('lot-children', definition=self, auth=app.auth)
if self.AUTH:
lot_children = app.auth.requires_auth(lot_children)
self.add_url_rule('/<{}:{}>/children'.format(self.ID_CONVERTER.value, self.ID_NAME), self.add_url_rule('/<{}:{}>/children'.format(self.ID_CONVERTER.value, self.ID_NAME),
view_func=children, view_func=lot_children,
methods={'POST', 'DELETE'}) methods={'POST', 'DELETE'})
children = LotDeviceView.as_view('lot-device', definition=self, auth=app.auth) lot_device = LotDeviceView.as_view('lot-device', definition=self, auth=app.auth)
if self.AUTH:
lot_device = app.auth.requires_auth(lot_device)
self.add_url_rule('/<{}:{}>/devices'.format(self.ID_CONVERTER.value, self.ID_NAME), self.add_url_rule('/<{}:{}>/devices'.format(self.ID_CONVERTER.value, self.ID_NAME),
view_func=children, view_func=lot_device,
methods={'POST', 'DELETE'}) methods={'POST', 'DELETE'})
def init_db(self, db: 'db.SQLAlchemy'): def init_db(self, db: 'db.SQLAlchemy'):

View File

@ -23,7 +23,7 @@ class Lot(Thing):
A closed lot cannot be modified anymore. A closed lot cannot be modified anymore.
""" """
devices = db.relationship(Device, devices = db.relationship(Device,
backref=db.backref('parents', lazy=True, collection_class=set), backref=db.backref('lots', lazy=True, collection_class=set),
secondary=lambda: LotDevice.__table__, secondary=lambda: LotDevice.__table__,
collection_class=set) collection_class=set)
""" """

View File

@ -6,6 +6,7 @@ from flask import request
from teal.resource import View from teal.resource import View
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.lot.models import Lot from ereuse_devicehub.resources.lot.models import Lot
@ -30,9 +31,6 @@ class LotBaseChildrenView(View):
lots from a lot. lots from a lot.
""" """
class ListArgs(ma.Schema):
id = ma.fields.List(ma.fields.UUID())
def __init__(self, definition: 'Resource', **kw) -> None: def __init__(self, definition: 'Resource', **kw) -> None:
super().__init__(definition, **kw) super().__init__(definition, **kw)
self.list_args = self.ListArgs() self.list_args = self.ListArgs()
@ -73,6 +71,9 @@ class LotChildrenView(LotBaseChildrenView):
Ex. ``lot/<id>/children/id=X&id=Y``. Ex. ``lot/<id>/children/id=X&id=Y``.
""" """
class ListArgs(ma.Schema):
id = ma.fields.List(ma.fields.UUID())
def _post(self, lot: Lot, ids: Set[uuid.UUID]): def _post(self, lot: Lot, ids: Set[uuid.UUID]):
for id in ids: for id in ids:
lot.add_child(id) # todo what to do if child exists already? lot.add_child(id) # todo what to do if child exists already?
@ -88,9 +89,11 @@ class LotDeviceView(LotBaseChildrenView):
Ex. ``lot/<id>/devices/id=X&id=Y``. Ex. ``lot/<id>/devices/id=X&id=Y``.
""" """
def _post(self, lot: Lot, ids: Set[uuid.UUID]): class ListArgs(ma.Schema):
# todo this works? id = ma.fields.List(ma.fields.Integer())
lot.devices |= ids
def _delete(self, lot: Lot, ids: Set[uuid.UUID]): def _post(self, lot: Lot, ids: Set[int]):
lot.devices -= ids lot.devices.update(Device.query.filter(Device.id.in_(ids)))
def _delete(self, lot: Lot, ids: Set[int]):
lot.devices.difference_update(Device.query.filter(Device.id.in_(ids)))

View File

@ -3,6 +3,7 @@ from flask import g
from ereuse_devicehub.client import UserClient from ereuse_devicehub.client import UserClient
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
from ereuse_devicehub.devicehub import Devicehub
from ereuse_devicehub.resources.device.models import Desktop from ereuse_devicehub.resources.device.models import Desktop
from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.enums import ComputerChassis
from ereuse_devicehub.resources.lot.models import Lot, LotDevice from ereuse_devicehub.resources.lot.models import Lot, LotDevice
@ -38,7 +39,7 @@ def test_lot_device_relationship():
assert lot_device.lot_id == lot.id assert lot_device.lot_id == lot.id
assert lot_device.created assert lot_device.created
assert lot_device.author_id == g.user.id assert lot_device.author_id == g.user.id
assert device.parents == {lot} assert device.lots == {lot}
@pytest.mark.usefixtures(conftest.auth_app_context.__name__) @pytest.mark.usefixtures(conftest.auth_app_context.__name__)
@ -219,8 +220,29 @@ def test_post_add_children_view(user: UserClient):
assert parent['children'][0]['id'] == child['id'] assert parent['children'][0]['id'] == child['id']
child, _ = user.get(res=Lot, item=child['id']) child, _ = user.get(res=Lot, item=child['id'])
assert child['parents'][0]['id'] == parent['id'] assert child['parents'][0]['id'] == parent['id']
return child['id']
@pytest.mark.xfail(reason='Just develop the test') def test_lot_post_add_remove_device_view(app: Devicehub, user: UserClient):
def test_post_add_device_view(user: UserClient): """Tests adding a device to a lot using POST and
pass removing it with DELETE."""
with app.app_context():
device = Desktop(serial_number='foo',
model='bar',
manufacturer='foobar',
chassis=ComputerChassis.Lunchbox)
db.session.add(device)
db.session.commit()
device_id = device.id
parent, _ = user.post(({'name': 'lot'}), res=Lot)
lot, _ = user.post({},
res=Lot,
item='{}/devices'.format(parent['id']),
query=[('id', device_id)])
assert lot['devices'][0]['id'] == device_id
# Remove the device
lot, _ = user.delete(res=Lot,
item='{}/devices'.format(parent['id']),
query=[('id', device_id)],
status=200)
assert not len(lot['devices'])