Update pagination and return URL for Lot, Device, Event resources
This commit is contained in:
parent
d1a23cbf9d
commit
4f0493c464
|
@ -5,6 +5,7 @@ from itertools import chain
|
|||
from operator import attrgetter
|
||||
from typing import Dict, List, Set
|
||||
|
||||
from boltons import urlutils
|
||||
from citext import CIText
|
||||
from ereuse_utils.naming import Naming
|
||||
from sqlalchemy import BigInteger, Boolean, Column, Enum as DBEnum, Float, ForeignKey, Integer, \
|
||||
|
@ -17,6 +18,7 @@ from stdnum import imei, meid
|
|||
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, URL, check_lower, \
|
||||
check_range
|
||||
from teal.marshmallow import ValidationError
|
||||
from teal.resource import url_for_resource
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
|
||||
|
@ -56,9 +58,7 @@ class Device(Thing):
|
|||
"""
|
||||
depth = Column(Float(decimal_return_scale=3), check_range('depth', 0.1, 3))
|
||||
color = Column(ColorType)
|
||||
color.comment = """
|
||||
|
||||
"""
|
||||
color.comment = """The predominant color of the device."""
|
||||
|
||||
@property
|
||||
def events(self) -> list:
|
||||
|
@ -93,6 +93,11 @@ class Device(Thing):
|
|||
and not getattr(c, 'foreign_keys', None)
|
||||
and c.key not in {'id', 'type', 'created', 'updated', 'parent_id', 'hid'}}
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
"""The URL where to GET this device."""
|
||||
return urlutils.URL(url_for_resource(Device, item_id=self.id))
|
||||
|
||||
@declared_attr
|
||||
def __mapper_args__(cls):
|
||||
"""
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from typing import Dict, List, Set
|
||||
|
||||
from boltons import urlutils
|
||||
from boltons.urlutils import URL
|
||||
from colour import Color
|
||||
from sqlalchemy import Column, Integer
|
||||
|
@ -51,6 +52,9 @@ class Device(Thing):
|
|||
self.tags = ... # type: Set[Tag]
|
||||
self.lots = ... # type: Set[Lot]
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
pass
|
||||
|
||||
class DisplayMixin:
|
||||
technology = ... # type: Column
|
||||
|
|
|
@ -29,6 +29,7 @@ class Device(Thing):
|
|||
height = Float(validate=Range(0.1, 3), unit=UnitCodes.m, description=m.Device.height.comment)
|
||||
events = NestedOn('Event', many=True, dump_only=True, description=m.Device.events.__doc__)
|
||||
events_one = NestedOn('Event', many=True, load_only=True, collection_class=OrderedSet)
|
||||
url = URL(dump_only=True, description=m.Device.url.__doc__)
|
||||
|
||||
@pre_load
|
||||
def from_events_to_events_one(self, data: dict):
|
||||
|
|
|
@ -114,7 +114,10 @@ class DeviceView(View):
|
|||
'page': devices.page,
|
||||
'perPage': devices.per_page,
|
||||
'total': devices.total,
|
||||
}
|
||||
'previous': devices.prev_num,
|
||||
'next': devices.next_num
|
||||
},
|
||||
'url': request.path
|
||||
}
|
||||
return jsonify(ret)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from datetime import datetime, timedelta
|
|||
from typing import Set, Union
|
||||
from uuid import uuid4
|
||||
|
||||
from boltons import urlutils
|
||||
from citext import CIText
|
||||
from flask import current_app as app, g
|
||||
from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \
|
||||
|
@ -17,6 +18,7 @@ from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, IP, POLYMOR
|
|||
POLYMORPHIC_ON, StrictVersionType, URL, check_lower, check_range
|
||||
from teal.enums import Country, Currency, Subdivision
|
||||
from teal.marshmallow import ValidationError
|
||||
from teal.resource import url_for_resource
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.agent.models import Agent
|
||||
|
@ -163,6 +165,11 @@ class Event(Thing):
|
|||
would point to the computer that contained this data storage, if any.
|
||||
"""
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
"""The URL where to GET this event."""
|
||||
return urlutils.URL(url_for_resource(Event, item_id=self.id))
|
||||
|
||||
# noinspection PyMethodParameters
|
||||
@declared_attr
|
||||
def __mapper_args__(cls):
|
||||
|
|
|
@ -5,6 +5,7 @@ from distutils.version import StrictVersion
|
|||
from typing import Dict, List, Set, Union
|
||||
from uuid import UUID
|
||||
|
||||
from boltons import urlutils
|
||||
from boltons.urlutils import URL
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy.orm import relationship
|
||||
|
@ -62,6 +63,9 @@ class Event(Thing):
|
|||
self.agent = ... # type: Agent
|
||||
self.author = ... # type: User
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
pass
|
||||
|
||||
class EventWithOneDevice(Event):
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ import decimal
|
|||
from flask import current_app as app
|
||||
from marshmallow import Schema as MarshmallowSchema, ValidationError, validates_schema
|
||||
from marshmallow.fields import Boolean, DateTime, Decimal, Float, Integer, List, Nested, String, \
|
||||
TimeDelta, URL, UUID
|
||||
TimeDelta, UUID
|
||||
from marshmallow.validate import Length, Range
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from teal.enums import Country, Currency, Subdivision
|
||||
from teal.marshmallow import EnumField, IP, SanitizedStr, Version
|
||||
from teal.marshmallow import EnumField, IP, SanitizedStr, Version, URL
|
||||
from teal.resource import Schema
|
||||
|
||||
from ereuse_devicehub.marshmallow import NestedOn
|
||||
|
@ -38,6 +38,7 @@ class Event(Thing):
|
|||
author = NestedOn(User, dump_only=True, exclude=('token',))
|
||||
components = NestedOn(Component, dump_only=True, many=True)
|
||||
parent = NestedOn(Computer, dump_only=True, description=m.Event.parent_id.comment)
|
||||
url = URL(dump_only=True, description=m.Event.url.__doc__)
|
||||
|
||||
|
||||
class EventWithOneDevice(Event):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import uuid
|
||||
from datetime import datetime
|
||||
|
||||
from boltons import urlutils
|
||||
from citext import CIText
|
||||
from flask import g
|
||||
from sqlalchemy import TEXT
|
||||
|
@ -9,6 +10,7 @@ from sqlalchemy.sql import expression as exp
|
|||
from sqlalchemy_utils import LtreeType
|
||||
from sqlalchemy_utils.types.ltree import LQUERY
|
||||
from teal.db import UUIDLtree
|
||||
from teal.resource import url_for_resource
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.device.models import Device
|
||||
|
@ -61,6 +63,11 @@ class Lot(Thing):
|
|||
assert isinstance(child, uuid.UUID)
|
||||
Path.delete(self.id, child)
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
"""The URL where to GET this event."""
|
||||
return urlutils.URL(url_for_resource(Lot, item_id=self.id))
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
"""The children lots."""
|
||||
|
|
|
@ -3,6 +3,7 @@ from datetime import datetime
|
|||
from typing import Iterable, Set, Union
|
||||
from uuid import UUID
|
||||
|
||||
from boltons import urlutils
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy.orm import Query, relationship
|
||||
from sqlalchemy_utils import Ltree
|
||||
|
@ -46,6 +47,9 @@ class Lot(Thing):
|
|||
def parents(self) -> LotQuery:
|
||||
pass
|
||||
|
||||
@property
|
||||
def url(self) -> urlutils.URL:
|
||||
pass
|
||||
|
||||
class Path:
|
||||
id = ... # type: Column
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from marshmallow import fields as f
|
||||
from teal.marshmallow import SanitizedStr
|
||||
from teal.marshmallow import SanitizedStr, URL
|
||||
|
||||
from ereuse_devicehub.marshmallow import NestedOn
|
||||
from ereuse_devicehub.resources.device.schemas import Device
|
||||
|
@ -15,3 +15,4 @@ class Lot(Thing):
|
|||
devices = NestedOn(Device, many=True, dump_only=True)
|
||||
children = NestedOn('Lot', many=True, dump_only=True)
|
||||
parents = NestedOn('Lot', many=True, dump_only=True)
|
||||
url = URL(dump_only=True, description=m.Lot.url.__doc__)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from enum import Enum
|
||||
|
||||
from marshmallow import post_load
|
||||
from marshmallow.fields import DateTime, List, String, URL
|
||||
from marshmallow.fields import DateTime, List, String
|
||||
from teal.marshmallow import URL
|
||||
from teal.resource import Schema
|
||||
|
||||
from ereuse_devicehub.resources import models as m
|
||||
|
@ -20,7 +21,6 @@ class UnitCodes(Enum):
|
|||
|
||||
class Thing(Schema):
|
||||
type = String(description='Only required when it is nested.')
|
||||
url = URL(dump_only=True, description='The URL of the resource.')
|
||||
same_as = List(URL(dump_only=True), dump_only=True, data_key='sameAs')
|
||||
updated = DateTime('iso', dump_only=True, description=m.Thing.updated.comment.strip())
|
||||
created = DateTime('iso', dump_only=True, description=m.Thing.created.comment.strip())
|
||||
|
|
|
@ -30,6 +30,7 @@ class TestConfig(DevicehubConfig):
|
|||
TESTING = True
|
||||
ORGANIZATION_NAME = 'FooOrg'
|
||||
ORGANIZATION_TAX_ID = 'foo-org-id'
|
||||
SERVER_NAME = 'localhost'
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
|
|
|
@ -102,6 +102,8 @@ def test_device_query(user: UserClient):
|
|||
"""Checks result of inventory."""
|
||||
user.post(conftest.file('basic.snapshot'), res=Snapshot)
|
||||
i, _ = user.get(res=Device)
|
||||
assert i['url'] == '/devices/'
|
||||
assert i['items'][0]['url'] == '/devices/1'
|
||||
pc = next(d for d in i['items'] if d['type'] == 'Desktop')
|
||||
assert len(pc['events']) == 4
|
||||
assert len(pc['components']) == 3
|
||||
|
|
Reference in a new issue