def update_from_query_string(request, Model, query, adapter):
    headers = request.response.headers
    if request.params:
        # TODO: Implement schema validation to use request.validated
        querystring = QueryString(request, Model, adapter=adapter)
        total_query = querystring.from_filter_by(query)
        total_query = querystring.from_tags(total_query)
        query = querystring.from_order_by(total_query)
        query = querystring.from_limit(query)
        query = querystring.from_offset(query)
        # TODO: Advanced pagination with Link Header
        # Link: '<https://api.github.com/user/repos?page=3&per_page=100>;
        # rel="next",
        # <https://api.github.com/user/repos?page=50&per_page=100>;
        # rel="last"'
        headers['X-Count-Records'] = str(query.count())
        headers['X-Total-Records'] = str(total_query.count())
        # TODO: Etag / timestamp / 304 if no changes
        # TODO: Cache headers
        return query
    else:
        # no querystring, returns all records (maybe we will want to apply
        # some default filters values
        headers['X-Count-Records'] = str(query.count())
        headers['X-Total-Records'] = str(query.count())
        return query
Exemplo n.º 2
0
    def read(cls, request):
        # check user is disconnected
        # check user has access rigth to see this resource
        model = request.params['context[model]']

        fields = cls.parse_fields(
            request.params['context[fields]'],
            model,
            request.authenticated_userid,
        )

        # TODO complex case of relationship
        Model = cls.anyblok.get(model)
        adapter = Model.get_furetui_adapter()
        qs = QueryString(request, Model, adapter=adapter)
        query = cls.anyblok.Pyramid.restrict_query_by_user(
            qs.Model.query(), request.authenticated_userid)
        query = qs.from_filter_by(query)
        query = qs.from_filter_by_primary_keys(query)
        query = qs.from_composite_filter_by(query)
        query = qs.from_tags(query)

        query2 = qs.from_order_by(query)
        query2 = qs.from_limit(query2)
        query2 = qs.from_offset(query2)

        query2 = query2.options(*cls.add_options(deepcopy(fields), model))

        data = []
        pks = []

        def append_result(fields, model_name, entry):
            model = cls.anyblok.get(model_name)
            fd = model.fields_description()
            current_fields = fields.pop("__fields")
            current_fields.extend(fields.keys())
            data.append({
                'type': 'UPDATE_DATA',
                'model': model_name,
                'pk': entry.to_primary_keys(),
                'data': entry.to_dict(*current_fields),
            })
            for field, subfield in fields.items():
                children_entries = getattr(entry, field)
                if children_entries:
                    if fd[field]['type'] in ('Many2One', 'One2One'):
                        children_entries = [children_entries]
                    for child_entry in children_entries:
                        append_result(deepcopy(fields[field]),
                                      fd[field]['model'], child_entry)

        for entry in query2:
            pks.append(entry.to_primary_keys())
            append_result(deepcopy(fields), model, entry)

        # query.count do a sub query, we do not want it, because mysql
        # has a terrible support of subqueries
        # total = query.with_entities(func.count('*')).scalar()
        total = query.count()
        return {
            'pks': pks,
            'total': total,
            'data': data,
        }