def item_view_object_with_select_calculated_properties(context, request):
    properties = item_links(context, request)
    qs = QueryString(request)
    select_properties = qs.param_values_to_list(params=qs.get_field_filters())
    calculated = calculate_select_properties(
        context, request, ns=properties, select_properties=select_properties)
    properties.update(calculated)
    return properties
class Cart:
    '''
    Pass either a request with a query string with `?cart=foo&cart=bar` params
    or a list of uuids (@ids also work):
    * `cart = Cart(request)` or `cart = Cart(request, uuids=['xyz'])`
    * `cart.elements` return all elements in the cart(s)
    * `cart.as_params()` return [('@id', '/elements/xyz')] tuples for use in filters
    Can use max_cart_elements to limit total number of elements allowed in carts.
    Default is no limit.
    '''
    def __init__(self, request, uuids=None, max_cart_elements=None):
        self.request = request
        self.query_string = QueryString(request)
        self.uuids = uuids or []
        self.max_cart_elements = max_cart_elements
        self._elements = []

    def _get_carts_from_params(self):
        return self.query_string.param_values_to_list(
            params=self.query_string.get_cart())

    def _get_cart_object_or_error(self, uuid):
        return self.request.embed(uuid, '@@object')

    def _try_to_get_cart_object(self, uuid):
        try:
            cart = self._get_cart_object_or_error(uuid)
        except KeyError:
            cart = {}
        return cart

    def _try_to_get_elements_from_cart(self, uuid):
        cart = self._try_to_get_cart_object(uuid)
        return cart.get('elements', [])

    def _get_elements_from_carts(self):
        carts = self.uuids or self._get_carts_from_params()
        for cart in carts:
            yield from self._try_to_get_elements_from_cart(cart)

    def _validate_cart_size(self):
        if self.max_cart_elements is not None and len(
                self._elements) > self.max_cart_elements:
            raise HTTPBadRequest(explanation=(
                f'Too many elements in cart '
                f'(total {len(self._elements)} > max {self.max_cart_elements})'
            ))

    @property
    def elements(self):
        if not self._elements:
            self._elements = sorted(set(self._get_elements_from_carts()))
        self._validate_cart_size()
        yield from self._elements

    def as_params(self):
        return [('@id', at_id) for at_id in self.elements]