示例#1
0
 def assertQsParams(self, queryset, expected, url=None):
     # fix the fact the the test test uniq value, but the
     # compiler return a dict of list (even if there is on element each times)
     compiler = SQLCompiler(queryset.query, connections['api'], 'api')
     compiler.setup_query()
     pk, params = compiler.build_params_and_pk()
     if url:
         self.assertEqual(url, get_resource_path(queryset.model, pk=pk))
     self.assertEqual(dict_of_set(params), dict_of_set(expected))
示例#2
0
def api_struct_check(app_configs, **kwargs):
    from rest_models.backend.compiler import get_resource_path  # NOQA
    from rest_models.router import RestModelRouter  # NOQA

    errors = []

    all_models = []
    if app_configs is None:
        all_models.extend(apps.get_models())
    else:
        for app_config in app_configs:
            all_models.extend(app_config.get_models())
    router = RestModelRouter()
    models = ((router.get_api_connexion(model).cursor(), model)
              for model in all_models
              if router.is_api_model(model) and not bool(
                  router.get_api_connexion(model).settings_dict['OPTIONS'].get(
                      'SKIP_CHECK', False)))

    for db, rest_model in models:
        url = get_resource_path(rest_model)
        res = db.options(url)
        if res.status_code != 200:
            errors.append(
                Error(
                    'the remote api does not respond to us. OPTIONS %s%s => %s'
                    % (db.url, url, res.status_code),
                    hint=
                    'check the url for the remote api or the resource_path',
                    obj=rest_model,
                    id='rest_models.E001'))
            continue
        options = res.json()
        missings = {
            'include[]', 'exclude[]', 'filter{}', 'page', 'per_page', 'sort[]'
        } - set(options.get("features", []))
        if missings:
            errors.append(
                Error(
                    'the remote api does not support the folowing features: %s'
                    % missings,
                    hint='is the api on %s/%s running with dynamic-rest ?' %
                    (db.url, url),
                    obj=rest_model,
                    id='rest_models.E002'))
            continue
        for field in rest_model._meta.get_fields():
            field_name = field.concrete and field.db_column or field.name
            if field.is_relation:
                if router.is_api_model(field.related_model):
                    if field_name not in options['properties']:
                        errors.append(
                            Error(
                                'the field %s.%s in not present on the remote serializer'
                                % (rest_model.__name__, field_name),
                                obj="%s.%s" %
                                (rest_model.__name__, field_name),
                                hint=
                                'check if the serializer on %s/%s has a field "%s"'
                                % (db.url, url, field_name),
                                id='rest_models.E003'))
                    else:
                        type_is_many = options['properties'][field_name][
                            'type'] == 'many'
                        type_is_one = options['properties'][field_name][
                            'type'] == 'one'
                        if (type_is_many and
                                not (field.one_to_many or field.many_to_many)
                                or type_is_one and
                                not (field.one_to_one or field.many_to_one)):

                            errors.append(
                                Error(
                                    'the field %s.%s many does not match the api'
                                    % (rest_model.__name__, field_name),
                                    obj="%s.%s" %
                                    (rest_model.__name__, field_name),
                                    hint=
                                    'check if the serializer at %s%s have a Serializer.many '
                                    'value corresponding to the local model %s'
                                    % (db.url, url, field_name),
                                    id='rest_models.E005'))

                        choice_count = len(
                            options['properties'][field_name].get(
                                'choices', []))
                        if choice_count > 100:
                            errors.append(
                                Warning(
                                    'the field %s.%s has many choices values (%s) in OPTIONS '
                                    'and it slow down the check' %
                                    (rest_model.__name__, field_name,
                                     choice_count),
                                    obj="%s.%s" %
                                    (rest_model.__name__, field_name),
                                    hint=
                                    'check if the serializer at %s%s provide '
                                    'a choices with less values for %s' %
                                    (db.url, url, field_name),
                                    id='rest_models.W001'))

            elif field_name not in options['properties']:
                errors.append(
                    Error(
                        'the field %s.%s in not present on the remote serializer'
                        % (rest_model.__name__, field_name),
                        hint='check if the serializer on %s%s has a field "%s"'
                        % (db.url, url, field_name),
                        id='rest_models.E006'))
    return errors