Beispiel #1
0
    def render_tag(self, context, *tag_args, **tag_kwargs):
        data = self.get_context_data(context, *tag_args, **tag_kwargs)
        new_context = self.get_context(context, data)

        if django.VERSION >= (1, 8):
            t = context.render_context.get(self)
            if t is None:
                file_name = self.get_template_name(*tag_args, **tag_kwargs)

                if isinstance(file_name, Template):
                    t = file_name
                elif isinstance(getattr(file_name, 'template', None), Template):
                    t = file_name.template
                elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
                    t = context.template.engine.select_template(file_name)
                else:
                    t = context.template.engine.get_template(file_name)
                context.render_context[self] = t

            return t.render(new_context)
        else:
            # Get template nodes, and cache it.
            # Note that self.nodelist has a special meaning in the Node base class.
            if not getattr(self, 'nodelist', None):
                file_name = self.get_template_name(*tag_args, **tag_kwargs)

                if not isinstance(file_name, six.string_types) and is_iterable(file_name):
                    tpl = select_template(file_name)
                else:
                    tpl = get_template(file_name)

                self.nodelist = tpl.nodelist

            # Render the node
            return self.nodelist.render(new_context)
 def _check_choices(self, klass=None):
     klass = klass or self.model
     if hasattr(klass, self.choices_name):
         choices = getattr(klass, self.choices_name)
         if (isinstance(choices, six.string_types) or not is_iterable(choices)):
             return [
                 checks.Error(
                     "'{0}' must be an iterable (e.g., a list or tuple).".format(self.choices_name),
                     hint=None,
                     obj=klass,
                     id='lazychoices.E001',
                 ),
             ]
         elif any(isinstance(choice, six.string_types) or
                  not is_iterable(choice) or len(choice) != 2
                  for choice in choices):
             return [
                 checks.Error(
                     ("'{0}' must be an iterable containing "
                      '(actual value, human readable name) tuples.').format(self.choices_name),
                     hint=None,
                     obj=klass,
                     id='lazychoices.E002',
                 ),
             ]
         else:
             return []
     else:
         return []
Beispiel #3
0
    def resolve(self, value):
        bits = self.path.split(".")

        for bit in bits:
            if is_iterable(value):
                value = ", ".join(map(lambda v: smart_str(self.resolve_one(v, bit)), value))
            else:
                value = self.resolve_one(value, bit)

        if isinstance(value, self.raw_types):
            return value
        if is_iterable(value):
            return ", ".join(map(smart_str, value))

        return value and smart_str(value) or None
    def render(self, context):
        """
        Renders the specified template and context. Caches the
        template object in render_context to avoid reparsing and
        loading when used in a for loop.

        A lot of this is token from django.template.base's InclusionNode.
        This behavior should be changed if we upgrade to Django 1.8.
        """
        try:
            snugget = self.snugget.resolve(context)
            file_name = snugget.getRelatedTemplate()
            context['snugget'] = snugget
        except (template.base.VariableDoesNotExist):
            return ''

        from django.template.loader import get_template, select_template
        from django.utils.itercompat import is_iterable
        if isinstance(file_name, template.Template):
            t = file_name
        elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
            t = select_template(file_name)
        else:
            t = get_template(file_name)
        return t.render(context)
def parse_dt(str):
    str = str.strip()
    if str and is_iterable(str):
        try:
            return make_aware(parse(str, dayfirst=True), UTC())
        except Exception as e:
            import pdb; pdb.set_trace()
Beispiel #6
0
                def render(self, context):
                    resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
                    if takes_context:
                        args = [context] + resolved_vars
                    else:
                        args = resolved_vars

                    dict = func(*args)

                    if not getattr(self, 'nodelist', False):
                        from django.template.loader import get_template, select_template
                        if isinstance(file_name, Template):
                            t = file_name
                        elif not isinstance(file_name, basestring) and is_iterable(file_name):
                            t = select_template(file_name)
                        else:
                            t = get_template(file_name)
                        self.nodelist = t.nodelist
                    new_context = context_class(dict, **{
                        'autoescape': context.autoescape,
                        'current_app': context.current_app,
                        'use_l10n': context.use_l10n,
                    })
                    # Copy across the CSRF token, if present, because inclusion
                    # tags are often used for forms, and we need instructions
                    # for using CSRF protection to be as simple as possible.
                    csrf_token = context.get('csrf_token', None)
                    if csrf_token is not None:
                        new_context['csrf_token'] = csrf_token
                    return self.nodelist.render(new_context)
Beispiel #7
0
    def render(self, context):
        """
        Render the specified template and context. Cache the template object
        in render_context to avoid reparsing and loading when used in a for
        loop.
        """
        resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
        _dict = self.func(*resolved_args, **resolved_kwargs)

        t = context.render_context.get(self)
        if t is None:
            if isinstance(self.filename, Template):
                t = self.filename
            elif isinstance(getattr(self.filename, 'template', None), Template):
                t = self.filename.template
            elif not isinstance(self.filename, six.string_types) and is_iterable(self.filename):
                t = context.template.engine.select_template(self.filename)
            else:
                t = context.template.engine.get_template(self.filename)
            context.render_context[self] = t
        new_context = context.new(_dict)
        # Copy across the CSRF token, if present, because inclusion tags are
        # often used for forms, and we need instructions for using CSRF
        # protection to be as simple as possible.
        csrf_token = context.get('csrf_token')
        if csrf_token is not None:
            new_context['csrf_token'] = csrf_token
        return t.render(new_context)
            def render(self, context):
                resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
                args = [context] + resolved_vars
                my_cache_key = self.calculate_cache_key(args)
                if my_cache_key:
                    output = cache.cache.get(my_cache_key)
                    if output:
                        return output
                returnval = func(*args)
                if not returnval:
                    return ""
                (file_name, dict_) = returnval

                if file_name not in self.nodelists:
                    if not isinstance(file_name, str) and is_iterable(file_name):
                        t = select_template(file_name)
                    else:
                        t = get_template(file_name)
                    self.nodelists[file_name] = t.nodelist
                new_context = Context(dict_)
                # Copy across the CSRF token, if present, because inclusion
                # tags are often used for forms, and we need instructions
                # for using CSRF protection to be as simple as possible.
                csrf_token = context.get('csrf_token', None)
                if csrf_token is not None:
                    new_context['csrf_token'] = csrf_token
                output = self.nodelists[file_name].render(new_context)
                if my_cache_key:
                    cache.cache.set(my_cache_key, output, cache_time)
                return output
    def __init__(self, do, on, field_name, sender, sender_model, commit, field_holder_getter):
        self.freeze = False
        self.field_name = field_name
        self.commit = commit
        self.wait_connect = False
        #sender has priority
        if sender is not None:
            sender_model = sender

        #waiting for models defined as strings
        if isinstance(sender_model, basestring):
            model = models.get_model(*sender_model.split(".", 1), seed_cache=False)
            if model is None:
               self.wait_connect = True
               _wait_triggers[sender_model.split(".", 1)[1]] = self
            else:
                sender_model = model

        self.sender = sender_model

        if not do:
            raise ValueError("`do` action not defined for trigger")
        self.do = do

        if not is_iterable(on):
            on = [on]
        self.on = on

        self.field_holder_getter = field_holder_getter
    def render(self, context):
        """
        Renders the specified template and context. Caches the
        template object in render_context to avoid reparsing and
        loading when used in a for loop.

        A lot of this is taken from django.template.base's InclusionNode, for Django 1.8.6.
        Upgrading Django should mean updating this to match.
        """
        try:
            snugget = self.snugget.resolve(context)
            file_name = snugget.getRelatedTemplate()
            context['snugget'] = snugget
        except (template.base.VariableDoesNotExist):
            return ''

        from django.utils.itercompat import is_iterable
        if isinstance(file_name, template.Template):
            t = file_name
        elif isinstance(getattr(file_name, 'template', None), template.Template):
            t = file_name.template
        elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
            t = context.template.engine.select_template(file_name)
        else:
            t = context.template.engine.get_template(file_name)
        context.render_context[self] = t
        return t.render(context)
Beispiel #11
0
            def render_given_args(self, resolved_args, context_attrs):
                context = self._context
                # CHANGED: func -> cached_func
                _dict = cached_func(*resolved_args)

                t = context.render_context.get(self)
                if t is None:
                    if isinstance(file_name, Template):
                        t = file_name
                    elif isinstance(getattr(file_name, 'template', None), Template):
                        t = file_name.template
                    elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
                        t = context.template.engine.select_template(file_name)
                    else:
                        t = context.template.engine.get_template(file_name)
                    context.render_context[self] = t
                # CHANGED: new_context = context.new(_dict) to the following
                # five lines.  We don't want to copy the context because it
                # might be a RequestContext, even if the tag's cache doesn't
                # depend on this user.  This would be Very Bad; it could cause
                # the cache to leak data about one user to another user.  So we
                # require using a plain Context, and copy a whitelisted set of
                # attrs over, rather than using copy().
                new_context = Context(_dict)
                for attr, val in context_attrs.iteritems():
                    setattr(new_context, attr, val)
                new_context.render_context = copy(context.render_context)
                # CHANGED: removed copying the csrf_token over to the
                # new_context, because we should never do that.  If you need a
                # csrf_token in an inclusion tag, you'll have to generate your
                # own with AJAX.
                return t.render(new_context)
Beispiel #12
0
 def render(self, context):
     resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
     if file_name is None:
         f, _dict = func(*resolved_args, **resolved_kwargs)
     else:
         f, _dict = file_name, func(*resolved_args, **resolved_kwargs)
     # Empiric bug fix: without the or True only the first minimodule in a for loop get rendered completly. Very weird bug, no idea why this fix it
     if not getattr(self, 'nodelist', False) or True:
         from django.template.loader import get_template, select_template
         if isfunction(f):
             f = f(context)
         if isinstance(f, template.Template):
             t = f
         elif not isinstance(f, str) and is_iterable(f):
             t = select_template(f)
         else:
             t = get_template(f)
         self.nodelist = t.nodelist
     new_context = context_class(_dict, **{
         'autoescape': context.autoescape,
         'current_app': context.current_app,
         'use_l10n': context.use_l10n,
         'use_tz': context.use_tz,
     })
     # Copy across the CSRF token, if present, because
     # inclusion tags are often used for forms, and we need
     # instructions for using CSRF protection to be as simple
     # as possible.
     csrf_token = context.get('csrf_token', None)
     if csrf_token is not None:
         new_context['csrf_token'] = csrf_token
     return self.nodelist.render(new_context)
Beispiel #13
0
                def render(self, context):
                    resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
                    _dict = func(*resolved_args, **resolved_kwargs)

                    if not getattr(self, 'nodelist', False):
                        from django.template.loader import get_template, select_template
                        if isinstance(file_name, Template):
                            t = file_name
                        elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
                            t = select_template(file_name)
                        else:
                            t = get_template(file_name)
                        self.nodelist = t.nodelist
                    new_context = context_class(_dict, **{
                        'autoescape': context.autoescape,
                        'current_app': context.current_app,
                        'use_l10n': context.use_l10n,
                        'use_tz': context.use_tz,
                    })
                    # Copy across the CSRF token, if present, because
                    # inclusion tags are often used for forms, and we need
                    # instructions for using CSRF protection to be as simple
                    # as possible.
                    csrf_token = context.get('csrf_token', None)
                    if csrf_token is not None:
                        new_context['csrf_token'] = csrf_token
                    return self.nodelist.render(new_context)
Beispiel #14
0
    def _update_method(self, instance):
        """
            Generic `update_FOO` method that is connected to model
        """
        qs_getter = self.update_method["queryset"]
        if qs_getter is None:
            qs_getter = [instance]

        trigger = self.update_method["do"]

        setattr(instance, trigger.field_name, self.update_method["initial"])
        if callable(qs_getter):
            qs = qs_getter(instance)
        else:
            qs = qs_getter

        if not is_iterable(qs):
            qs = [qs]

        for obj in qs:
            setattr(
                instance,
                trigger.field_name,
                trigger.do(instance, obj, trigger.on[0])
            )

        instance.save()
Beispiel #15
0
    def __init__(self, choices, *args, **kwargs):
        if isinstance(choices, type) and issubclass(choices, extypes_base.BaseConstrainedSet):
            set_definition = choices
            if hasattr(choices.choices, "items"):
                django_choices = list(choices.choices.items())
            else:
                django_choices = [(c, c) for c in choices.choices]

        else:
            if not is_iterable(choices):
                raise ValueError("choices must be an iterable of (code, human_readable) tuples; got %r" % (choices,))

            for item in choices:
                if len(item) != 2:
                    raise ValueError(
                        "choices must be an iterable of (code, human_readable) tuples; got entry %r in %r"
                        % (item, choices)
                    )

            django_choices = choices
            set_definition = extypes.ConstrainedSet(datastructures.SortedDict(django_choices))

        for opt in set_definition.choices:
            if self.db_separator in opt:
                raise ValueError("%r is forbidden in choices; found in %r" % (self.db_separator, opt))

        self.django_choices = django_choices
        self.set_definition = set_definition
        kwargs["max_length"] = len(self.get_prep_value(set_definition.choices))
        super(SetField, self).__init__(*args, **kwargs)
    def get_db_prep_lookup(self, value, connection):
        if not is_iterable(value):
            value = [value]
        ret = []
        for elem in value:
            ret.append((ContentType.objects.get_for_model(elem).pk, elem.pk))

        return (",".join(["%s"]*len(value)),ret)
Beispiel #17
0
    def resolve(self, value):
        bits = self.path.split(".")

        for bit in bits:
            if is_iterable(value):
                value = u', '.join(
                    map(lambda v: force_unicode(self.resolve_one(v, bit)), value)
                )
            else:
                value = self.resolve_one(value, bit)

        if isinstance(value, self.raw_types):
            return value
        if is_iterable(value):
            return u', '.join(map(force_unicode, value))

        return value and force_unicode(value) or None
Beispiel #18
0
 def get_answer(self):
     if self.question.text_answer:
         return unicode(self.cleaned_data['text_answer']).strip()
     
     a = self.cleaned_data['answer']
     if not is_iterable(a):
         a = [a]
     return a
Beispiel #19
0
def to_list(arg):
    """
    to_list
    @return: lst or [arg]
    """
    if is_iterable(arg) and not isinstance(arg, dict):
        return list(arg)
    else:
        return [arg]
Beispiel #20
0
    def hash(self, value):
        """
        Generate a hash of the given iterable.

        This is for use in a cache key.
        """
        if is_iterable(value):
            value = tuple(to_bytestring(v) for v in value)
        return hashlib.md5(six.b(':').join(value)).hexdigest()
Beispiel #21
0
    def __init__(self, model, field, name, trigger, commons, update_method):
        self.model = model
        self.name = name
        self.trigger = []

        if not commons:
            commons = {}
        self.commons = commons

        if not is_iterable(trigger) or isinstance(trigger, dict):
            trigger = [trigger]

        trigger_defaults = dict(
            sender_model=model,
            sender=None,
            on=[models.signals.post_save],
            field_holder_getter=lambda instance: instance,
            field_name=name,
            commit=True
        )
        trigger_defaults.update(commons)

        if not len(trigger):
            raise ValueError("At least one trigger must be specefied")

        for t in trigger:
            trigger_meta = trigger_defaults.copy()
            trigger_meta.update(t)

            trigger_obj = Trigger(**trigger_meta)
            if trigger_obj.wait_connect is False:
                trigger_obj.connect()

            self.trigger.append(trigger_obj)

        update_method_defaults = dict(
            initial=None,
            name="update_%s" % name,
            do=self.trigger[0],
            queryset=None
        )
        update_method_defaults.update(update_method)

        if isinstance(update_method_defaults["do"], (int, long)):
            n = update_method_defaults["do"]
            if n >= len(self.trigger):
                raise ValueError("Update method trigger must be index of trigger list")
            update_method_defaults["do"] = self.trigger[update_method_defaults["do"]]

        self.update_method = update_method_defaults

        setattr(model, self.update_method["name"], lambda instance: self._update_method(instance))
        setattr(model, "freeze_%s" % name, lambda instance: self.set_freeze(True))
        setattr(model, "unfreeze_%s" % name, lambda instance: self.set_freeze(False))
Beispiel #22
0
def get_consts(mod):
    export_names = getattr(mod, 'EXPORTS', [])

    if not is_iterable(export_names):
        raise TypeError('`%s.EXPORTS` must be an iterable.' % mod.__name__)

    consts = {}

    for name in export_names:
        consts[name] = parse(getattr(mod, name))

    return consts
Beispiel #23
0
    def normalize_fields(cls, fields):
        """
        Normalize the fields into an ordered map of {field name: param name}
        """
        # fields is a mapping, copy into new OrderedDict
        if isinstance(fields, dict):
            return OrderedDict(fields)

        # convert iterable of values => iterable of pairs (field name, param name)
        assert is_iterable(fields), \
            "'fields' must be an iterable (e.g., a list, tuple, or mapping)."

        # fields is an iterable of field names
        assert all(isinstance(field, six.string_types) or
                   is_iterable(field) and len(field) == 2  # may need to be wrapped in parens
                   for field in fields), \
            "'fields' must contain strings or (field name, param name) pairs."

        return OrderedDict([
            (f, f) if isinstance(f, six.string_types) else f for f in fields
        ])
Beispiel #24
0
def encode_multipart(boundary, data):
    """
    Encodes multipart POST data from a dictionary of form values.

    The key will be used as the form data name; the value will be transmitted
    as content. If the value is a file, the contents of the file will be sent
    as an application/octet-stream; otherwise, str(value) will be sent.
    """
    lines = []
    to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)

    # Not by any means perfect, but good enough for our purposes.
    is_file = lambda thing: hasattr(thing, "read") and callable(thing.read)

    # Each bit of the multipart form data could be either a form value or a
    # file, or a *list* of form values and/or files. Remember that HTTP field
    # names can be duplicated!
    for (key, value) in data.items():
        if is_file(value):
            lines.extend(encode_file(boundary, key, value))
        elif not isinstance(value, six.string_types) and is_iterable(value):
            if len(value):
                for item in value:
                    if is_file(item):
                        lines.extend(encode_file(boundary, key, item))
                    else:
                        lines.extend([to_bytes(val) for val in [
                            '--%s' % boundary,
                            'Content-Disposition: form-data; name="%s"' % key,
                            '',
                            item
                        ]])
            else:
                lines.extend([to_bytes(val) for val in [
                    '--%s' % boundary,
                    'Content-Disposition: form-data; name="%s"' % key,
                    '',
                    ''
                ]])
        else:
            lines.extend([to_bytes(val) for val in [
                '--%s' % boundary,
                'Content-Disposition: form-data; name="%s"' % key,
                '',
                value
            ]])

    lines.extend([
        to_bytes('--%s--' % boundary),
        b'',
    ])
    return b'\r\n'.join(lines)
Beispiel #25
0
def register(app_name, modules):
    """
    simple module registering for later usage
    we don't want to import admin.py in models.py
    """
    global INSTALLED_APPS_REGISTER
    mod_list = INSTALLED_APPS_REGISTER.get(app_name, [])

    if isinstance(modules, six.string_types):
        mod_list.append(modules)
    elif is_iterable(modules):
        mod_list.extend(modules)

    INSTALLED_APPS_REGISTER[app_name] = mod_list
    def options(self, name, value, attrs=None):
        """Return only select options."""
        # When the data hasn't validated, we get the raw input
        if isinstance(value, six.text_type):
            value = value.split(',')

        for v in value:
            if not v:
                continue

            real_values = v.split(',') if hasattr(v, 'split') else v
            real_values = [real_values] if not is_iterable(real_values) else real_values
            for rv in real_values:
                yield self.option_value(rv)
    def get_db_prep_lookup(self, value, connection):
        if django.VERSION < (1, 10):
            value = value[0]

        if isinstance(value, QuerySet):
            value = value.query

        if isinstance(value, Query):
            # QuerSet was passed. Don't fetch its items. Use server-side
            # subselect, which will be faster. Get the content_type_id
            # from django_content_type table.

            compiler = value.get_compiler(connection=connection)

            compiled_query, compiled_args = compiler.as_sql()

            query = """
            SELECT
                %(django_content_type_db_table)s.id AS content_type_id,
                U0.id AS object_id
            FROM
                %(django_content_type_db_table)s,
                (%(compiled_query)s) U0
            WHERE
                %(django_content_type_db_table)s.model = '%(model)s' AND
                %(django_content_type_db_table)s.app_label = '%(app_label)s'
            """ % dict(
                django_content_type_db_table=ContentType._meta.db_table,
                compiled_query=compiled_query,
                model=value.model._meta.model_name,
                app_label=value.model._meta.app_label)

            return query, compiled_args

        if is_iterable(value):
            buf = []
            for elem in value:
                if isinstance(elem, Model):
                    buf.append(
                        (ContentType.objects.get_for_model(elem).pk, elem.pk))
                else:
                    raise FilteredGenericForeignKeyFilteringException(
                        "Unknown type: %r" % type(elem))

            query = ",".join(["%s"] * len(buf))
            return query, buf

        raise NotImplementedError(
            "You passed %r and I don't know what to do with it" % value)
Beispiel #28
0
                def real_render(*args):
                    dict = func(*args)

                    if not getattr(self, 'nodelist', False):
                        from django.template.loader import get_template, select_template
                        if not isinstance(file_name, basestring) and is_iterable(file_name):
                            t = select_template(file_name)
                        else:
                            t = get_template(file_name)
                        self.nodelist = t.nodelist

                    result = self.nodelist.render(context_class(dict,
                            autoescape= context.autoescape))

                    return result
    def format_value(self, value):
        """Return the list of HTML option values for a form field value."""
        if not isinstance(value, (tuple, list)):
            value = [value]

        values = set()
        for v in value:
            if not v:
                continue

            v = v.split(',') if isinstance(v, six.string_types) else v
            v = [v] if not is_iterable(v) else v
            for t in v:
                values.add(self.option_value(t))
        return values
Beispiel #30
0
    def handler(self, signal, instance=None, **kwargs):
        """
            Signal handler
        """
        if self.freeze:
            return

        objects = self.field_holder_getter(instance)
        if not is_iterable(objects):
            objects = [objects]

        for obj in objects:
            setattr(obj, self.field_name, self.do(obj, instance, signal))

            if self.commit:
                obj.save()
Beispiel #31
0
        def method(self, context, nodes, *arg, **kwargs):
            _dict = func(self, context, nodes, *arg, **kwargs)
            from django.template.loader import get_template, select_template
            cls_str = str if six.PY3 else basestring
            if isinstance(file_name, Template):
                t = file_name
            elif not isinstance(file_name, cls_str) and is_iterable(file_name):
                t = select_template(file_name)
            else:
                t = get_template(file_name)

            _dict['autoescape'] = context.autoescape
            _dict['use_l10n'] = context.use_l10n
            _dict['use_tz'] = context.use_tz
            _dict['admin_view'] = context['admin_view']

            csrf_token = context.get('csrf_token', None)
            if csrf_token is not None:
                _dict['csrf_token'] = csrf_token
            nodes.append(t.render(_dict))
Beispiel #32
0
 def method(self, context, nodes, *arg, **kwargs):
     _dict = func(self, context, nodes, *arg, **kwargs)
     from django.template.loader import get_template, select_template
     if isinstance(file_name, Template):
         t = file_name
     elif not isinstance(file_name, basestring) and is_iterable(file_name):
         t = select_template(file_name)
     else:
         t = get_template(file_name)
     new_context = context_class(_dict, **{
         'autoescape': context.autoescape,
         'current_app': context.current_app,
         'use_l10n': context.use_l10n,
         'use_tz': context.use_tz,
     })
     new_context['admin_view'] = context['admin_view']
     csrf_token = context.get('csrf_token', None)
     if csrf_token is not None:
         new_context['csrf_token'] = csrf_token
     nodes.append(t.render(new_context))
Beispiel #33
0
    def get_template_names(self):
        """
        Returns a list of template names to be used for the request. May
        not be called if render_to_response is overridden.
        """
        names = []
        if isinstance(self.template_name, six.string_types):
            names.append(self.template_name)
        elif is_iterable(self.template_name):
            names.extend(self.template_name)

        model = self.get_model()
        if model is not None:
            args = (
                model._meta.app_label,
                model._meta.model_name,
                self.template_name_suffix,
            )
            names.append('{0}/{1}{2}.html'.format(*args))

        return names
Beispiel #34
0
    def run_checks(self, app_configs=None, tags=None, include_deployment_checks=False):
        """
        Run all registered checks and return list of Errors and Warnings.
        """
        errors = []
        checks = self.get_checks(include_deployment_checks)

        if tags is not None:
            checks = [check for check in checks if not set(check.tags).isdisjoint(tags)]
        else:
            # By default, 'database'-tagged checks are not run as they do more
            # than mere static code analysis.
            checks = [check for check in checks if Tags.database not in check.tags]

        for check in checks:
            new_errors = check(app_configs=app_configs)
            assert is_iterable(new_errors), (
                    "The function %r did not return a list. All functions registered "
                    "with the checks registry must return a list." % check)
            errors.extend(new_errors)
        return errors
Beispiel #35
0
    def parse_token(cls, parser, token):
        bits = token.split_contents()
        tag_name = bits[0]
        args, kwargs = cls.parse_arguments(parser, tag_name, bits[1:])

        t = kwargs.pop('template', cls.template)
        if isinstance(t, Template):
            template = t
        elif isinstance(t, six.string_types):
            template = get_template(t).template
        elif is_iterable(t):
            template = select_template(t).template
        else:
            template = Template('')

        return {
            'tag_name': tag_name,
            'args': args,
            'kwargs': kwargs,
            'template': template,
        }
Beispiel #36
0
                def render(self, context):
                    resolved_vars = [
                        var.resolve(context) for var in self.vars_to_resolve
                    ]
                    if takes_context:
                        args = [context] + resolved_vars
                    else:
                        args = resolved_vars

                    dict = func(*args)

                    if not getattr(self, 'nodelist', False):
                        from django.template.loader import get_template, select_template
                        if not isinstance(file_name,
                                          str) and is_iterable(file_name):
                            t = select_template(file_name)
                        else:
                            t = get_template(file_name)
                        self.nodelist = t.nodelist
                    return self.nodelist.render(
                        context_class(dict, autoescape=context.autoescape))
Beispiel #37
0
def send(user, template, module, url=None, target=None, **kwargs):
    """send notification.

    The core method to send a notification

    Arguments:
        user {User} -- The receiver.
        template {str} -- The message template.
        url {str} -- The corresponding URL.
        module {str} -- The logical group.
        **kwargs {dict} -- Exrta data for template rendering.
    """
    def get_arguments(user):
        return dict(user=user,
                    template=template,
                    url=url,
                    module=module,
                    target=target,
                    data=formatter.extract_variables(template,
                                                     user=user,
                                                     url=url,
                                                     module=module,
                                                     target=target,
                                                     **kwargs))

    if url is None:
        url = target.get_absolute_url()

    if not registry.has_module(module):
        raise registry.RegistryError("Module %r not found." % module)
    print(user)
    if is_iterable(user):
        args = []
        for u in user:
            args.append(get_arguments(u))

        return Notification.objects.bulk_create(
            map(lambda arg: Notification(**arg), args))
    else:
        return Notification.objects.create(**get_arguments(user))
Beispiel #38
0
    def __init__(self, *args, **kwargs):
        self.dim = kwargs.pop('dim', 1)
        self.units = kwargs.pop('units', None)

        if not isinstance(self.dim, int) or (self.dim < 1):
            raise ValidationError(self.error_messages['invalid_dim'])

        if not is_iterable(self.units):
            raise ValidationError(self.error_messages['require_units'])

        if any(not isinstance(u, (ureg.Unit, str)) for u in self.units):
            raise ValidationError(self.error_messages['invalid_units'])

        self.units = list(
            map(lambda u: isinstance(u, str) and ureg(u) or u, self.units))

        if any(u.dimensionality != self.units[0].dimensionality
               for u in self.units):
            raise ValidationError(self.error_messages['different_units'])

        kwargs['max_length'] = 255
        super().__init__(*args, **kwargs)
Beispiel #39
0
    def run_checks(self,
                   app_configs=None,
                   tags=None,
                   include_deployment_checks=False):
        """ Run all registered checks and return list of Errors and Warnings.
        """
        errors = []
        checks = self.get_checks(include_deployment_checks)

        if tags is not None:
            checks = [
                check for check in checks
                if hasattr(check, 'tags') and set(check.tags) & set(tags)
            ]

        for check in checks:
            new_errors = check(app_configs=app_configs)
            assert is_iterable(new_errors), (
                "The function %r did not return a list. All functions registered "
                "with the checks registry must return a list." % check)
            errors.extend(new_errors)
        return errors
    def handler(self, signal, instance=None, **kwargs):
        """
            Signal handler
        """
        if self.freeze:
            return

        try:
            objects = self.field_holder_getter(instance)
        except ObjectDoesNotExist:
            return

        if not objects:
            return

        if not is_iterable(objects):
            objects = [objects]

        for obj in objects:
            setattr(obj, self.field_name, self.do(obj, instance, signal))

            if self.commit:
                obj.save()
Beispiel #41
0
    def _check_allowed_countries(self):
        if not self.allowed_countries:
            return []

        if not is_iterable(self.allowed_countries):
            return [
                checks.Error(
                    "'allowed_countries' must be an iterable (e.g. a list or tuple)",
                    obj=self,
                    id="agir.lib.E001",
                )
            ]

        if not all(isinstance(s, str) and len(s) == 2 for s in self.allowed_countries):
            return [
                checks.Error(
                    "'allowed_countries' must be an iterable containing 2-letters country codes",
                    obj=self,
                    id="agir.lib.E002",
                )
            ]

        return []
Beispiel #42
0
 def __init__(self, formats, *args, **kwargs):
     if formats is None:
         raise ImproperlyConfigured('StdNumField defined without formats')
     if not is_iterable(formats) or isinstance(formats, string_types):
         formats = [formats]
     for format in formats:
         if format not in settings.DEFAULT_FORMATS:
             raise ValueError(
                 'Unknown format for StdNumField: "{}". Is it missing from '
                 'settings.STDNUMFIELD["DEFAULT_FORMATS"]?'.format(
                     format, ))
     if 'alphabets' in kwargs:
         alphabets = kwargs.pop('alphabets')
         alphabets = listify(alphabets)
     else:
         alphabets = None
     self.formats = formats
     self.alphabets = alphabets
     # TODO make dynamic when/if stdnum provides this data:
     kwargs["max_length"] = 254
     super(StdNumField, self).__init__(*args, **kwargs)
     self.validators.append(
         StdnumFormatValidator(self.formats, self.alphabets))
    def run_checks(self,
                   app_configs=None,
                   tags=None,
                   include_deployment_checks=False,
                   databases=None):
        """调用检查函数,返回一个包含错误或警告的列表
        """
        # self 是「“检查对象”收集器 registry」
        errors = []
        # 调用自身的方法获取已经收集到的「检查函数」的列表
        checks = self.get_checks(include_deployment_checks)
        #print('【django.core.checks.registry...run_checks】checks:')
        #for c in checks:
        #    print('\t', c)

        if tags is not None:
            checks = [
                check for check in checks
                if not set(check.tags).isdisjoint(tags)
            ]

        # 下面这个 checks 变量是一个列表,里面是来自各个包中的 checks 模块中的函数:
        # django.core.checks.model_checks.check_lazy_references
        # django.core.checks.model_checks.check_all_models(接下来研究这个)
        # django.contrib.auth.checks.check_user_model(和这个)
        # django.core.checks.urls.check_url_config
        # django.core.checks.urls.check_url_namespaces_unique
        # ... ...
        # 我们分析的是 python manage.py makemigrations 命令,所以主要研究第 2、3 个函数
        for check in checks:
            new_errors = check(app_configs=app_configs, databases=databases)
            assert is_iterable(new_errors), (
                "The function %r did not return a list. All functions registered "
                "with the checks registry must return a list." % check)
            errors.extend(new_errors)
        return errors
    def __init__(self, do, on, field_name, sender, sender_model, commit,\
                 field_holder_getter):
        self.freeze = False
        self.field_name = field_name
        self.commit = commit

        if sender_model and not sender:
            if isinstance(sender_model, basestring):
                sender_model = models.get_model(*sender_model.split(".", 1))

            self.sender = self.sender_model = sender_model
        else:
            self.sender = sender
            self.sender_model = sender_model

        if not do:
            raise ValueError("`do` action not defined for trigger")
        self.do = do

        if not is_iterable(on):
            on = [on]
        self.on = on

        self.field_holder_getter = field_holder_getter
Beispiel #45
0
                def render(self, context):
                    resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
                    if takes_context:
                        args = [context] + resolved_vars
                    else:
                        args = resolved_vars

                    dict = func(*args)

                    if not getattr(self, 'nodelist', False):
                        from django.template.loader import get_template, select_template
                        if not isinstance(file_name, basestring) and is_iterable(file_name):
                            t = select_template(file_name)
                        else:
                            t = get_template(file_name)
                        self.nodelist = t.nodelist
                    new_context = context_class(dict, autoescape=context.autoescape)
                    # Copy across the CSRF token, if present, because inclusion
                    # tags are often used for forms, and we need instructions
                    # for using CSRF protection to be as simple as possible.
                    csrf_token = context.get('csrf_token', None)
                    if csrf_token is not None:
                        new_context['csrf_token'] = csrf_token
                    return self.nodelist.render(new_context)
Beispiel #46
0
def get_validation_errors(outfile, app=None):
    """
    Validates all models that are part of the specified app. If no app name is provided,
    validates all models of all installed apps. Writes errors, if any, to outfile.
    Returns number of errors.
    """
    from django.db import models, connection
    from django.db.models.loading import get_app_errors
    from django.db.models.fields.related import RelatedObject
    from django.db.models.deletion import SET_NULL, SET_DEFAULT

    e = ModelErrorCollection(outfile)

    for (app_name, error) in get_app_errors().items():
        e.add(app_name, error)

    for cls in models.get_models(app):
        opts = cls._meta

        # Check swappable attribute.
        if opts.swapped:
            try:
                app_label, model_name = opts.swapped.split('.')
            except ValueError:
                e.add(opts, "%s is not of the form 'app_label.app_name'." % opts.swappable)
                continue
            if not models.get_model(app_label, model_name):
                e.add(opts, "Model has been swapped out for '%s' which has not been installed or is abstract." % opts.swapped)
            # No need to perform any other validation checks on a swapped model.
            continue

        # Model isn't swapped; do field-specific validation.
        for f in opts.local_fields:
            if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
                e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
            if f.name.endswith('_'):
                e.add(opts, '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.' % f.name)
            if (f.primary_key and f.null and
                    not connection.features.interprets_empty_strings_as_nulls):
                # We cannot reliably check this for backends like Oracle which
                # consider NULL and '' to be equal (and thus set up
                # character-based fields a little differently).
                e.add(opts, '"%s": Primary key fields cannot have null=True.' % f.name)
            if isinstance(f, models.CharField):
                try:
                    max_length = int(f.max_length)
                    if max_length <= 0:
                        e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name)
                except (ValueError, TypeError):
                    e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name)
            if isinstance(f, models.DecimalField):
                decimalp_ok, mdigits_ok = False, False
                decimalp_msg = '"%s": DecimalFields require a "decimal_places" attribute that is a non-negative integer.'
                try:
                    decimal_places = int(f.decimal_places)
                    if decimal_places < 0:
                        e.add(opts, decimalp_msg % f.name)
                    else:
                        decimalp_ok = True
                except (ValueError, TypeError):
                    e.add(opts, decimalp_msg % f.name)
                mdigits_msg = '"%s": DecimalFields require a "max_digits" attribute that is a positive integer.'
                try:
                    max_digits = int(f.max_digits)
                    if max_digits <= 0:
                        e.add(opts,  mdigits_msg % f.name)
                    else:
                        mdigits_ok = True
                except (ValueError, TypeError):
                    e.add(opts, mdigits_msg % f.name)
                invalid_values_msg = '"%s": DecimalFields require a "max_digits" attribute value that is greater than or equal to the value of the "decimal_places" attribute.'
                if decimalp_ok and mdigits_ok:
                    if decimal_places > max_digits:
                        e.add(opts, invalid_values_msg % f.name)
            if isinstance(f, models.FileField) and not f.upload_to:
                e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
            if isinstance(f, models.ImageField):
                # Try to import PIL in either of the two ways it can end up installed.
                try:
                    from PIL import Image
                except ImportError:
                    try:
                        import Image
                    except ImportError:
                        e.add(opts, '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
            if isinstance(f, models.BooleanField) and getattr(f, 'null', False):
                e.add(opts, '"%s": BooleanFields do not accept null values. Use a NullBooleanField instead.' % f.name)
            if isinstance(f, models.FilePathField) and not (f.allow_files or f.allow_folders):
                e.add(opts, '"%s": FilePathFields must have either allow_files or allow_folders set to True.' % f.name)
            if f.choices:
                if isinstance(f.choices, six.string_types) or not is_iterable(f.choices):
                    e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
                else:
                    for c in f.choices:
                        if not isinstance(c, (list, tuple)) or len(c) != 2:
                            e.add(opts, '"%s": "choices" should be a sequence of two-tuples.' % f.name)
            if f.db_index not in (None, True, False):
                e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)

            # Perform any backend-specific field validation.
            connection.validation.validate_field(e, opts, f)

            # Check if the on_delete behavior is sane
            if f.rel and hasattr(f.rel, 'on_delete'):
                if f.rel.on_delete == SET_NULL and not f.null:
                    e.add(opts, "'%s' specifies on_delete=SET_NULL, but cannot be null." % f.name)
                elif f.rel.on_delete == SET_DEFAULT and not f.has_default():
                    e.add(opts, "'%s' specifies on_delete=SET_DEFAULT, but has no default value." % f.name)

            # Check to see if the related field will clash with any existing
            # fields, m2m fields, m2m related objects or related objects
            if f.rel:
                if f.rel.to not in models.get_models():
                    e.add(opts, "'%s' has a relation with model %s, which has either not been installed or is abstract." % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, six.string_types):
                    continue

                # Make sure the model we're related hasn't been swapped out
                if f.rel.to._meta.swapped:
                    e.add(opts, "'%s' defines a relation with the model '%s.%s', which has been swapped out. Update the relation to point at settings.%s." % (f.name, f.rel.to._meta.app_label, f.rel.to._meta.object_name, f.rel.to._meta.swappable))

                # Make sure the related field specified by a ForeignKey is unique
                if not f.rel.to._meta.get_field(f.rel.field_name).unique:
                    e.add(opts, "Field '%s' under model '%s' must have a unique=True constraint." % (f.rel.field_name, f.rel.to.__name__))

                rel_opts = f.rel.to._meta
                rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
                rel_query_name = f.related_query_name()
                if not f.rel.is_hidden():
                    for r in rel_opts.fields:
                        if r.name == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                        if r.name == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    for r in rel_opts.local_many_to_many:
                        if r.name == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                        if r.name == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    for r in rel_opts.get_all_related_many_to_many_objects():
                        if r.get_accessor_name() == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                    for r in rel_opts.get_all_related_objects():
                        if r.field is not f:
                            if r.get_accessor_name() == rel_name:
                                e.add(opts, "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                            if r.get_accessor_name() == rel_query_name:
                                e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))

        seen_intermediary_signatures = []
        for i, f in enumerate(opts.local_many_to_many):
            # Check to see if the related m2m field will clash with any
            # existing fields, m2m fields, m2m related objects or related
            # objects
            if f.rel.to not in models.get_models():
                e.add(opts, "'%s' has an m2m relation with model %s, which has either not been installed or is abstract." % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, six.string_types):
                    continue

            # Make sure the model we're related hasn't been swapped out
            if f.rel.to._meta.swapped:
                e.add(opts, "'%s' defines a relation with the model '%s.%s', which has been swapped out. Update the relation to point at settings.%s." % (f.name, f.rel.to._meta.app_label, f.rel.to._meta.object_name, f.rel.to._meta.swappable))

            # Check that the field is not set to unique.  ManyToManyFields do not support unique.
            if f.unique:
                e.add(opts, "ManyToManyFields cannot be unique.  Remove the unique argument on '%s'." % f.name)

            if f.rel.through is not None and not isinstance(f.rel.through, six.string_types):
                from_model, to_model = cls, f.rel.to
                if from_model == to_model and f.rel.symmetrical and not f.rel.through._meta.auto_created:
                    e.add(opts, "Many-to-many fields with intermediate tables cannot be symmetrical.")
                seen_from, seen_to, seen_self = False, False, 0
                for inter_field in f.rel.through._meta.fields:
                    rel_to = getattr(inter_field.rel, 'to', None)
                    if from_model == to_model:  # relation to self
                        if rel_to == from_model:
                            seen_self += 1
                        if seen_self > 2:
                            e.add(opts, "Intermediary model %s has more than "
                                "two foreign keys to %s, which is ambiguous "
                                "and is not permitted." % (
                                    f.rel.through._meta.object_name,
                                    from_model._meta.object_name
                                )
                            )
                    else:
                        if rel_to == from_model:
                            if seen_from:
                                e.add(opts, "Intermediary model %s has more "
                                    "than one foreign key to %s, which is "
                                    "ambiguous and is not permitted." % (
                                        f.rel.through._meta.object_name,
                                         from_model._meta.object_name
                                     )
                                 )
                            else:
                                seen_from = True
                        elif rel_to == to_model:
                            if seen_to:
                                e.add(opts, "Intermediary model %s has more "
                                    "than one foreign key to %s, which is "
                                    "ambiguous and is not permitted." % (
                                        f.rel.through._meta.object_name,
                                        rel_to._meta.object_name
                                    )
                                )
                            else:
                                seen_to = True
                if f.rel.through not in models.get_models(include_auto_created=True):
                    e.add(opts, "'%s' specifies an m2m relation through model "
                        "%s, which has not been installed." % (f.name, f.rel.through)
                    )
                signature = (f.rel.to, cls, f.rel.through)
                if signature in seen_intermediary_signatures:
                    e.add(opts, "The model %s has two manually-defined m2m "
                        "relations through the model %s, which is not "
                        "permitted. Please consider using an extra field on "
                        "your intermediary model instead." % (
                            cls._meta.object_name,
                            f.rel.through._meta.object_name
                        )
                    )
                else:
                    seen_intermediary_signatures.append(signature)
                if not f.rel.through._meta.auto_created:
                    seen_related_fk, seen_this_fk = False, False
                    for field in f.rel.through._meta.fields:
                        if field.rel:
                            if not seen_related_fk and field.rel.to == f.rel.to:
                                seen_related_fk = True
                            elif field.rel.to == cls:
                                seen_this_fk = True
                    if not seen_related_fk or not seen_this_fk:
                        e.add(opts, "'%s' is a manually-defined m2m relation "
                            "through model %s, which does not have foreign keys "
                            "to %s and %s" % (f.name, f.rel.through._meta.object_name,
                                f.rel.to._meta.object_name, cls._meta.object_name)
                        )
            elif isinstance(f.rel.through, six.string_types):
                e.add(opts, "'%s' specifies an m2m relation through model %s, "
                    "which has not been installed" % (f.name, f.rel.through)
                )

            rel_opts = f.rel.to._meta
            rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
            rel_query_name = f.related_query_name()
            # If rel_name is none, there is no reverse accessor (this only
            # occurs for symmetrical m2m relations to self). If this is the
            # case, there are no clashes to check for this field, as there are
            # no reverse descriptors for this field.
            if rel_name is not None:
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.local_many_to_many:
                    if r.name == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))

        # Check ordering attribute.
        if opts.ordering:
            for field_name in opts.ordering:
                if field_name == '?':
                    continue
                if field_name.startswith('-'):
                    field_name = field_name[1:]
                if opts.order_with_respect_to and field_name == '_order':
                    continue
                # Skip ordering in the format field1__field2 (FIXME: checking
                # this format would be nice, but it's a little fiddly).
                if '__' in field_name:
                    continue
                # Skip ordering on pk. This is always a valid order_by field
                # but is an alias and therefore won't be found by opts.get_field.
                if field_name == 'pk':
                    continue
                try:
                    opts.get_field(field_name, many_to_many=False)
                except models.FieldDoesNotExist:
                    e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)

        # Check unique_together.
        for ut in opts.unique_together:
            for field_name in ut:
                try:
                    f = opts.get_field(field_name, many_to_many=True)
                except models.FieldDoesNotExist:
                    e.add(opts, '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
                else:
                    if isinstance(f.rel, models.ManyToManyRel):
                        e.add(opts, '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
                    if f not in opts.local_fields:
                        e.add(opts, '"unique_together" refers to %s. This is not in the same model as the unique_together statement.' % f.name)

    return len(e.errors)
Beispiel #47
0
def get_validation_errors(outfile, app=None):
    """
    Validates all models that are part of the specified app. If no app name is provided,
    validates all models of all installed apps. Writes errors, if any, to outfile.
    Returns number of errors.
    """
    from django.conf import settings
    from django.db import models, connection
    from django.db.models.loading import get_app_errors
    from django.db.models.fields.related import RelatedObject

    e = ModelErrorCollection(outfile)

    for (app_name, error) in get_app_errors().items():
        e.add(app_name, error)

    for cls in models.get_models(app):
        opts = cls._meta

        # Do field-specific validation.
        for f in opts.fields:
            if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
                e.add(
                    opts,
                    '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.'
                    % f.name)
            if f.name.endswith('_'):
                e.add(
                    opts,
                    '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.'
                    % f.name)
            if isinstance(f, models.CharField) and f.max_length in (None, 0):
                e.add(
                    opts,
                    '"%s": CharFields require a "max_length" attribute.' %
                    f.name)
            if isinstance(f, models.DecimalField):
                if f.decimal_places is None:
                    e.add(
                        opts,
                        '"%s": DecimalFields require a "decimal_places" attribute.'
                        % f.name)
                if f.max_digits is None:
                    e.add(
                        opts,
                        '"%s": DecimalFields require a "max_digits" attribute.'
                        % f.name)
            if isinstance(f, models.FileField) and not f.upload_to:
                e.add(
                    opts,
                    '"%s": FileFields require an "upload_to" attribute.' %
                    f.name)
            if isinstance(f, models.ImageField):
                try:
                    from PIL import Image
                except ImportError:
                    e.add(
                        opts,
                        '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .'
                        % f.name)
            if f.prepopulate_from is not None and type(
                    f.prepopulate_from) not in (list, tuple):
                e.add(
                    opts, '"%s": prepopulate_from should be a list or tuple.' %
                    f.name)
            if f.choices:
                if isinstance(f.choices,
                              basestring) or not is_iterable(f.choices):
                    e.add(
                        opts,
                        '"%s": "choices" should be iterable (e.g., a tuple or list).'
                        % f.name)
                else:
                    for c in f.choices:
                        if not type(c) in (tuple, list) or len(c) != 2:
                            e.add(
                                opts,
                                '"%s": "choices" should be a sequence of two-tuples.'
                                % f.name)
            if f.db_index not in (None, True, False):
                e.add(
                    opts,
                    '"%s": "db_index" should be either None, True or False.' %
                    f.name)

            # Check that max_length <= 255 if using older MySQL versions.
            if settings.DATABASE_ENGINE == 'mysql':
                db_version = connection.get_server_version()
                if db_version < (5, 0, 3) and isinstance(
                        f,
                    (models.CharField, models.CommaSeparatedIntegerField,
                     models.SlugField)) and f.max_length > 255:
                    e.add(
                        opts,
                        '"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).'
                        % (f.name, f.__class__.__name__, '.'.join(
                            [str(n) for n in db_version[:3]])))

            # Check to see if the related field will clash with any
            # existing fields, m2m fields, m2m related objects or related objects
            if f.rel:
                if f.rel.to not in models.get_models():
                    e.add(
                        opts,
                        "'%s' has relation with model %s, which has not been installed"
                        % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, (str, unicode)):
                    continue

                rel_opts = f.rel.to._meta
                rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
                rel_query_name = f.related_query_name()
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.many_to_many:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(
                                opts,
                                "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(
                                opts,
                                "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))

        for i, f in enumerate(opts.many_to_many):
            # Check to see if the related m2m field will clash with any
            # existing fields, m2m fields, m2m related objects or related objects
            if f.rel.to not in models.get_models():
                e.add(
                    opts,
                    "'%s' has m2m relation with model %s, which has not been installed"
                    % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, (str, unicode)):
                    continue

            rel_opts = f.rel.to._meta
            rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
            rel_query_name = f.related_query_name()
            # If rel_name is none, there is no reverse accessor.
            # (This only occurs for symmetrical m2m relations to self).
            # If this is the case, there are no clashes to check for this field, as
            # there are no reverse descriptors for this field.
            if rel_name is not None:
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.many_to_many:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(
                                opts,
                                "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(
                                opts,
                                "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))

        # Check admin attribute.
        if opts.admin is not None:
            if not isinstance(opts.admin, models.AdminOptions):
                e.add(
                    opts,
                    '"admin" attribute, if given, must be set to a models.AdminOptions() instance.'
                )
            else:
                # list_display
                if not isinstance(opts.admin.list_display, (list, tuple)):
                    e.add(
                        opts,
                        '"admin.list_display", if given, must be set to a list or tuple.'
                    )
                else:
                    for fn in opts.admin.list_display:
                        try:
                            f = opts.get_field(fn)
                        except models.FieldDoesNotExist:
                            if not hasattr(cls, fn):
                                e.add(
                                    opts,
                                    '"admin.list_display" refers to %r, which isn\'t an attribute, method or property.'
                                    % fn)
                        else:
                            if isinstance(f, models.ManyToManyField):
                                e.add(
                                    opts,
                                    '"admin.list_display" doesn\'t support ManyToManyFields (%r).'
                                    % fn)
                # list_display_links
                if opts.admin.list_display_links and not opts.admin.list_display:
                    e.add(
                        opts,
                        '"admin.list_display" must be defined for "admin.list_display_links" to be used.'
                    )
                if not isinstance(opts.admin.list_display_links,
                                  (list, tuple)):
                    e.add(
                        opts,
                        '"admin.list_display_links", if given, must be set to a list or tuple.'
                    )
                else:
                    for fn in opts.admin.list_display_links:
                        try:
                            f = opts.get_field(fn)
                        except models.FieldDoesNotExist:
                            if not hasattr(cls, fn):
                                e.add(
                                    opts,
                                    '"admin.list_display_links" refers to %r, which isn\'t an attribute, method or property.'
                                    % fn)
                        if fn not in opts.admin.list_display:
                            e.add(
                                opts,
                                '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".'
                                % fn)
                # list_filter
                if not isinstance(opts.admin.list_filter, (list, tuple)):
                    e.add(
                        opts,
                        '"admin.list_filter", if given, must be set to a list or tuple.'
                    )
                else:
                    for fn in opts.admin.list_filter:
                        try:
                            f = opts.get_field(fn)
                        except models.FieldDoesNotExist:
                            e.add(
                                opts,
                                '"admin.list_filter" refers to %r, which isn\'t a field.'
                                % fn)
                # date_hierarchy
                if opts.admin.date_hierarchy:
                    try:
                        f = opts.get_field(opts.admin.date_hierarchy)
                    except models.FieldDoesNotExist:
                        e.add(
                            opts,
                            '"admin.date_hierarchy" refers to %r, which isn\'t a field.'
                            % opts.admin.date_hierarchy)

        # Check ordering attribute.
        if opts.ordering:
            for field_name in opts.ordering:
                if field_name == '?': continue
                if field_name.startswith('-'):
                    field_name = field_name[1:]
                if opts.order_with_respect_to and field_name == '_order':
                    continue
                if '.' in field_name:
                    continue  # Skip ordering in the format 'table.field'.
                try:
                    opts.get_field(field_name, many_to_many=False)
                except models.FieldDoesNotExist:
                    e.add(
                        opts,
                        '"ordering" refers to "%s", a field that doesn\'t exist.'
                        % field_name)

        # Check core=True, if needed.
        for related in opts.get_followed_related_objects():
            if not related.edit_inline:
                continue
            try:
                for f in related.opts.fields:
                    if f.core:
                        raise StopIteration
                e.add(
                    related.opts,
                    "At least one field in %s should have core=True, because it's being edited inline by %s.%s."
                    % (related.opts.object_name, opts.module_name,
                       opts.object_name))
            except StopIteration:
                pass

        # Check unique_together.
        for ut in opts.unique_together:
            for field_name in ut:
                try:
                    f = opts.get_field(field_name, many_to_many=True)
                except models.FieldDoesNotExist:
                    e.add(
                        opts,
                        '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.'
                        % field_name)
                else:
                    if isinstance(f.rel, models.ManyToManyRel):
                        e.add(
                            opts,
                            '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.'
                            % f.name)

    return len(e.errors)
def _is_iterable(iterable):
    return not isinstance(iterable, basestring) and is_iterable(iterable)
Beispiel #49
0
def get_validation_errors(outfile, app=None):
    """
    Validates all models that are part of the specified app. If no app name is provided,
    validates all models of all installed apps. Writes errors, if any, to outfile.
    Returns number of errors.
    """
    from django.conf import settings
    from django.db import models, connection
    from django.db.models.loading import get_app_errors
    from django.db.models.fields.related import RelatedObject

    e = ModelErrorCollection(outfile)

    for (app_name, error) in get_app_errors().items():
        e.add(app_name, error)

    for cls in models.get_models(app):
        opts = cls._meta

        # Do field-specific validation.
        for f in opts.local_fields:
            if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
                e.add(
                    opts,
                    '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.'
                    % f.name)
            if f.name.endswith('_'):
                e.add(
                    opts,
                    '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.'
                    % f.name)
            if isinstance(f, models.CharField) and f.max_length in (None, 0):
                e.add(
                    opts,
                    '"%s": CharFields require a "max_length" attribute.' %
                    f.name)
            if isinstance(f, models.DecimalField):
                if f.decimal_places is None:
                    e.add(
                        opts,
                        '"%s": DecimalFields require a "decimal_places" attribute.'
                        % f.name)
                if f.max_digits is None:
                    e.add(
                        opts,
                        '"%s": DecimalFields require a "max_digits" attribute.'
                        % f.name)
            if isinstance(f, models.FileField) and not f.upload_to:
                e.add(
                    opts,
                    '"%s": FileFields require an "upload_to" attribute.' %
                    f.name)
            if isinstance(f, models.ImageField):
                try:
                    from PIL import Image
                except ImportError:
                    e.add(
                        opts,
                        '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .'
                        % f.name)
            if isinstance(f, models.BooleanField) and getattr(
                    f, 'null', False):
                e.add(
                    opts,
                    '"%s": BooleanFields do not accept null values. Use a NullBooleanField instead.'
                    % f.name)
            if f.choices:
                if isinstance(f.choices,
                              basestring) or not is_iterable(f.choices):
                    e.add(
                        opts,
                        '"%s": "choices" should be iterable (e.g., a tuple or list).'
                        % f.name)
                else:
                    for c in f.choices:
                        if not type(c) in (tuple, list) or len(c) != 2:
                            e.add(
                                opts,
                                '"%s": "choices" should be a sequence of two-tuples.'
                                % f.name)
            if f.db_index not in (None, True, False):
                e.add(
                    opts,
                    '"%s": "db_index" should be either None, True or False.' %
                    f.name)

            # Perform any backend-specific field validation.
            connection.validation.validate_field(e, opts, f)

            # Check to see if the related field will clash with any existing
            # fields, m2m fields, m2m related objects or related objects
            if f.rel:
                if f.rel.to not in models.get_models():
                    e.add(
                        opts,
                        "'%s' has a relation with model %s, which has either not been installed or is abstract."
                        % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, (str, unicode)):
                    continue

                rel_opts = f.rel.to._meta
                rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
                rel_query_name = f.related_query_name()
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.local_many_to_many:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(
                            opts,
                            "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(
                                opts,
                                "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(
                                opts,
                                "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))

        seen_intermediary_signatures = []
        for i, f in enumerate(opts.local_many_to_many):
            # Check to see if the related m2m field will clash with any
            # existing fields, m2m fields, m2m related objects or related
            # objects
            if f.rel.to not in models.get_models():
                e.add(
                    opts,
                    "'%s' has an m2m relation with model %s, which has either not been installed or is abstract."
                    % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, (str, unicode)):
                    continue

            # Check that the field is not set to unique.  ManyToManyFields do not support unique.
            if f.unique:
                e.add(
                    opts,
                    "ManyToManyFields cannot be unique.  Remove the unique argument on '%s'."
                    % f.name)

            if getattr(f.rel, 'through', None) is not None:
                if hasattr(f.rel, 'through_model'):
                    from_model, to_model = cls, f.rel.to
                    if from_model == to_model and f.rel.symmetrical:
                        e.add(
                            opts,
                            "Many-to-many fields with intermediate tables cannot be symmetrical."
                        )
                    seen_from, seen_to, seen_self = False, False, 0
                    for inter_field in f.rel.through_model._meta.fields:
                        rel_to = getattr(inter_field.rel, 'to', None)
                        if from_model == to_model:  # relation to self
                            if rel_to == from_model:
                                seen_self += 1
                            if seen_self > 2:
                                e.add(
                                    opts,
                                    "Intermediary model %s has more than two foreign keys to %s, which is ambiguous and is not permitted."
                                    % (f.rel.through_model._meta.object_name,
                                       from_model._meta.object_name))
                        else:
                            if rel_to == from_model:
                                if seen_from:
                                    e.add(
                                        opts,
                                        "Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted."
                                        %
                                        (f.rel.through_model._meta.object_name,
                                         from_model._meta.object_name))
                                else:
                                    seen_from = True
                            elif rel_to == to_model:
                                if seen_to:
                                    e.add(
                                        opts,
                                        "Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted."
                                        %
                                        (f.rel.through_model._meta.object_name,
                                         rel_to._meta.object_name))
                                else:
                                    seen_to = True
                    if f.rel.through_model not in models.get_models():
                        e.add(
                            opts,
                            "'%s' specifies an m2m relation through model %s, which has not been installed."
                            % (f.name, f.rel.through))
                    signature = (f.rel.to, cls, f.rel.through_model)
                    if signature in seen_intermediary_signatures:
                        e.add(
                            opts,
                            "The model %s has two manually-defined m2m relations through the model %s, which is not permitted. Please consider using an extra field on your intermediary model instead."
                            % (cls._meta.object_name,
                               f.rel.through_model._meta.object_name))
                    else:
                        seen_intermediary_signatures.append(signature)
                    seen_related_fk, seen_this_fk = False, False
                    for field in f.rel.through_model._meta.fields:
                        if field.rel:
                            if not seen_related_fk and field.rel.to == f.rel.to:
                                seen_related_fk = True
                            elif field.rel.to == cls:
                                seen_this_fk = True
                    if not seen_related_fk or not seen_this_fk:
                        e.add(
                            opts,
                            "'%s' has a manually-defined m2m relation through model %s, which does not have foreign keys to %s and %s"
                            %
                            (f.name, f.rel.through, f.rel.to._meta.object_name,
                             cls._meta.object_name))
                else:
                    e.add(
                        opts,
                        "'%s' specifies an m2m relation through model %s, which has not been installed"
                        % (f.name, f.rel.through))

            rel_opts = f.rel.to._meta
            rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
            rel_query_name = f.related_query_name()
            # If rel_name is none, there is no reverse accessor (this only
            # occurs for symmetrical m2m relations to self). If this is the
            # case, there are no clashes to check for this field, as there are
            # no reverse descriptors for this field.
            if rel_name is not None:
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.local_many_to_many:
                    if r.name == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(
                                opts,
                                "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(
                                opts,
                                "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'."
                                % (f.name, rel_opts.object_name,
                                   r.get_accessor_name(), f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(
                            opts,
                            "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(
                            opts,
                            "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'."
                            % (f.name, rel_opts.object_name,
                               r.get_accessor_name(), f.name))

        # Check ordering attribute.
        if opts.ordering:
            for field_name in opts.ordering:
                if field_name == '?': continue
                if field_name.startswith('-'):
                    field_name = field_name[1:]
                if opts.order_with_respect_to and field_name == '_order':
                    continue
                # Skip ordering in the format field1__field2 (FIXME: checking
                # this format would be nice, but it's a little fiddly).
                if '_' in field_name:
                    continue
                try:
                    opts.get_field(field_name, many_to_many=False)
                except models.FieldDoesNotExist:
                    e.add(
                        opts,
                        '"ordering" refers to "%s", a field that doesn\'t exist.'
                        % field_name)

        # Check unique_together.
        for ut in opts.unique_together:
            for field_name in ut:
                try:
                    f = opts.get_field(field_name, many_to_many=True)
                except models.FieldDoesNotExist:
                    e.add(
                        opts,
                        '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.'
                        % field_name)
                else:
                    if isinstance(f.rel, models.ManyToManyRel):
                        e.add(
                            opts,
                            '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.'
                            % f.name)
                    if f not in opts.local_fields:
                        e.add(
                            opts,
                            '"unique_together" refers to %s. This is not in the same model as the unique_together statement.'
                            % f.name)

    return len(e.errors)
Beispiel #50
0
def check_relate_settings(app_configs, **kwargs):
    errors = []

    # {{{ check RELATE_BASE_URL
    relate_base_url = getattr(settings, RELATE_BASE_URL, None)
    if relate_base_url is None:
        errors.append(
            RelateCriticalCheckMessage(msg=REQUIRED_CONF_ERROR_PATTERN %
                                       {"location": RELATE_BASE_URL},
                                       id="relate_base_url.E001"))
    elif not isinstance(relate_base_url, str):
        errors.append(
            RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                "location": RELATE_BASE_URL,
                "types": "str"
            }),
                                       id="relate_base_url.E002"))
    elif not relate_base_url.strip():
        errors.append(
            RelateCriticalCheckMessage(
                msg="%(location)s should not be an empty string" %
                {"location": RELATE_BASE_URL},
                id="relate_base_url.E003"))
    # }}}

    from accounts.utils import relate_user_method_settings
    # check RELATE_EMAIL_APPELLATION_PRIORITY_LIST
    errors.extend(
        relate_user_method_settings.check_email_appellation_priority_list())

    # check RELATE_CSV_SETTINGS
    errors.extend(relate_user_method_settings.check_custom_full_name_method())

    # check RELATE_USER_PROFILE_MASK_METHOD
    errors.extend(relate_user_method_settings.check_user_profile_mask_method())

    # {{{ check EMAIL_CONNECTIONS
    email_connections = getattr(settings, EMAIL_CONNECTIONS, None)
    if email_connections is not None:
        if not isinstance(email_connections, dict):
            errors.append(
                RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                    "location": EMAIL_CONNECTIONS,
                    "types": "dict"
                }),
                                           id="email_connections.E001"))
        else:
            for label, c in six.iteritems(email_connections):
                if not isinstance(c, dict):
                    errors.append(
                        RelateCriticalCheckMessage(
                            msg=(INSTANCE_ERROR_PATTERN % {
                                "location":
                                "'%s' in '%s'" % (label, EMAIL_CONNECTIONS),
                                "types":
                                "dict"
                            }),
                            id="email_connections.E002"))
                else:
                    if "backend" in c:
                        try:
                            import_string(c["backend"])
                        except ImportError as e:
                            errors.append(
                                RelateCriticalCheckMessage(
                                    msg=(GENERIC_ERROR_PATTERN % {
                                        "location":
                                        "'%s' in %s" %
                                        (label, RELATE_FACILITIES),
                                        "error_type":
                                        type(e).__name__,
                                        "error_str":
                                        str(e)
                                    }),
                                    id="email_connections.E003"))
    # }}}

    # {{{ check RELATE_FACILITIES

    relate_facilities_conf = getattr(settings, RELATE_FACILITIES, None)
    if relate_facilities_conf is not None:
        from course.utils import get_facilities_config
        try:
            facilities = get_facilities_config()
        except Exception as e:
            errors.append(
                RelateCriticalCheckMessage(msg=(GENERIC_ERROR_PATTERN % {
                    "location": RELATE_FACILITIES,
                    "error_type": type(e).__name__,
                    "error_str": str(e)
                }),
                                           id="relate_facilities.E001"))
        else:
            if not isinstance(facilities, dict):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "'%(location)s' must either be or return a dictionary"
                        % {
                            "location": RELATE_FACILITIES
                        }),
                                               id="relate_facilities.E002"))
            else:
                for facility, conf in six.iteritems(facilities):
                    if not isinstance(conf, dict):
                        errors.append(
                            RelateCriticalCheckMessage(
                                msg=(INSTANCE_ERROR_PATTERN % {
                                    "location":
                                    "Facility `%s` in %s" %
                                    (facility, RELATE_FACILITIES),
                                    "types":
                                    "dict"
                                }),
                                id="relate_facilities.E003"))
                    else:
                        ip_ranges = conf.get("ip_ranges", [])
                        if ip_ranges:
                            if not isinstance(ip_ranges, (list, tuple)):
                                errors.append(
                                    RelateCriticalCheckMessage(
                                        msg=(INSTANCE_ERROR_PATTERN % {
                                            "location":
                                            "'ip_ranges' in facility `%s` in %s"
                                            % (facilities, RELATE_FACILITIES),
                                            "types":
                                            "list or tuple"
                                        }),
                                        id="relate_facilities.E004"))
                            else:
                                for ip_range in ip_ranges:
                                    try:
                                        get_ip_network(ip_range)
                                    except Exception as e:
                                        errors.append(
                                            RelateCriticalCheckMessage(
                                                msg=(GENERIC_ERROR_PATTERN % {
                                                    "location":
                                                    "'ip_ranges' in "
                                                    "facility `%s` in %s" %
                                                    (facility,
                                                     RELATE_FACILITIES),
                                                    "error_type":
                                                    type(e).__name__,
                                                    "error_str":
                                                    str(e)
                                                }),
                                                id="relate_facilities.E005"))
                        else:
                            if not callable(relate_facilities_conf):
                                errors.append(
                                    Warning(msg=(
                                        "Faclity `%s` in %s is an open facility "
                                        "as it has no configured `ip_ranges`" %
                                        (facility, RELATE_FACILITIES)),
                                            id="relate_facilities.W001"))

    # }}}

    # {{{ check RELATE_MAINTENANCE_MODE_EXCEPTIONS
    relate_maintenance_mode_exceptions = getattr(
        settings, RELATE_MAINTENANCE_MODE_EXCEPTIONS, None)
    if relate_maintenance_mode_exceptions is not None:
        if not isinstance(relate_maintenance_mode_exceptions, (list, tuple)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_MAINTENANCE_MODE_EXCEPTIONS,
                        "types": "list or tuple"
                    }),
                    id="relate_maintenance_mode_exceptions.E001"))
        else:
            for ip in relate_maintenance_mode_exceptions:
                try:
                    get_ip_network(ip)
                except Exception as e:
                    errors.append(
                        RelateCriticalCheckMessage(
                            msg=(GENERIC_ERROR_PATTERN % {
                                "location":
                                "ip/ip_ranges '%s' in %s" %
                                (ip, RELATE_FACILITIES),
                                "error_type":
                                type(e).__name__,
                                "error_str":
                                str(e)
                            }),
                            id="relate_maintenance_mode_exceptions.E002"))
    # }}}

    # {{{ check RELATE_SESSION_RESTART_COOLDOWN_SECONDS
    relate_session_restart_cooldown_seconds = getattr(
        settings, RELATE_SESSION_RESTART_COOLDOWN_SECONDS, None)
    if relate_session_restart_cooldown_seconds is not None:
        if not isinstance(relate_session_restart_cooldown_seconds,
                          (int, float)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_SESSION_RESTART_COOLDOWN_SECONDS,
                        "types": "int or float"
                    }),
                    id="relate_session_restart_cooldown_seconds.E001"))
        else:
            if relate_session_restart_cooldown_seconds < 0:
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%(location)s must be a positive number, "
                             "got %(value)s instead" % {
                                 "location":
                                 RELATE_SESSION_RESTART_COOLDOWN_SECONDS,
                                 "value":
                                 relate_session_restart_cooldown_seconds
                             }),
                        id="relate_session_restart_cooldown_seconds.E002"))

    # }}}

    # {{{ check RELATE_TICKET_MINUTES_VALID_AFTER_USE
    relate_ticket_minutes_valid_after_use = getattr(
        settings, RELATE_TICKET_MINUTES_VALID_AFTER_USE, None)
    if relate_ticket_minutes_valid_after_use is not None:
        if not isinstance(relate_ticket_minutes_valid_after_use, (int, float)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_TICKET_MINUTES_VALID_AFTER_USE,
                        "types": "int or float"
                    }),
                    id="relate_ticket_minutes_valid_after_use.E001"))
        else:
            if relate_ticket_minutes_valid_after_use < 0:
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%(location)s must be a positive number, "
                             "got %(value)s instead" % {
                                 "location":
                                 RELATE_TICKET_MINUTES_VALID_AFTER_USE,
                                 "value": relate_ticket_minutes_valid_after_use
                             }),
                        id="relate_ticket_minutes_valid_after_use.E002"))

    # }}}

    # {{{ check GIT_ROOT
    git_root = getattr(settings, GIT_ROOT, None)
    if git_root is None:
        errors.append(
            RelateCriticalCheckMessage(msg=REQUIRED_CONF_ERROR_PATTERN %
                                       {"location": GIT_ROOT},
                                       id="git_root.E001"))
    elif not isinstance(git_root, str):
        errors.append(
            RelateCriticalCheckMessage(msg=INSTANCE_ERROR_PATTERN % {
                "location": GIT_ROOT,
                "types": "str"
            },
                                       id="git_root.E002"))
    else:
        if not os.path.isdir(git_root):
            errors.append(
                RelateCriticalCheckMessage(msg=(
                    "`%(path)s` connfigured in %(location)s is not a valid path"
                    % {
                        "path": git_root,
                        "location": GIT_ROOT
                    }),
                                           id="git_root.E003"))
        else:
            if not os.access(git_root, os.W_OK):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "`%(path)s` connfigured in %(location)s is not writable "
                        "by RELATE" % {
                            "path": git_root,
                            "location": GIT_ROOT
                        }),
                                               id="git_root.E004"))
            if not os.access(git_root, os.R_OK):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "`%(path)s` connfigured in %(location)s is not readable "
                        "by RELATE" % {
                            "path": git_root,
                            "location": GIT_ROOT
                        }),
                                               id="git_root.E005"))

    # }}}

    # {{{ check RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION
    relate_disable_codehilite_markdown_extension = getattr(
        settings, RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION, None)
    if relate_disable_codehilite_markdown_extension is not None:
        if not isinstance(relate_disable_codehilite_markdown_extension, bool):
            errors.append(
                Warning(
                    msg="%(location)s is not a Boolean value: `%(value)s`, "
                    "assuming True" % {
                        "location":
                        RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
                        "value":
                        repr(relate_disable_codehilite_markdown_extension)
                    },
                    id="relate_disable_codehilite_markdown_extension.W001"))
        elif not relate_disable_codehilite_markdown_extension:
            errors.append(
                Warning(
                    msg="%(location)s is set to False "
                    "(with 'markdown.extensions.codehilite' enabled'), "
                    "noticing that some pages with code fence markdown "
                    "might get crashed" % {
                        "location":
                        RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
                        "value":
                        repr(relate_disable_codehilite_markdown_extension)
                    },
                    id="relate_disable_codehilite_markdown_extension.W002"))

    # }}}

    # {{{ check LANGUAGES, why this is not done in django?

    languages = settings.LANGUAGES

    from django.utils.itercompat import is_iterable

    if (isinstance(languages, six.string_types) or not is_iterable(languages)):
        errors.append(
            RelateCriticalCheckMessage(
                msg=(INSTANCE_ERROR_PATTERN % {
                    "location": LANGUAGES,
                    "types": "an iterable (e.g., a list or tuple)."
                }),
                id="relate_languages.E001"))
    else:
        if any(
                isinstance(choice, six.string_types) or not is_iterable(choice)
                or len(choice) != 2 for choice in languages):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=("'%s' must be an iterable containing "
                         "(language code, language description) tuples, just "
                         "like the format of LANGUAGES setting ("
                         "https://docs.djangoproject.com/en/dev/ref/settings/"
                         "#languages)" % LANGUAGES),
                    id="relate_languages.E002"))
        else:
            from collections import OrderedDict
            options_dict = OrderedDict(tuple(settings.LANGUAGES))
            all_lang_codes = [
                lang_code
                for lang_code, lang_descr in tuple(settings.LANGUAGES)
            ]
            for lang_code in options_dict.keys():
                if all_lang_codes.count(lang_code) > 1:
                    errors.append(
                        Warning(msg=(
                            "Duplicate language entries were found in "
                            "settings.LANGUAGES for '%s', '%s' will be used "
                            "as its language_description" %
                            (lang_code, options_dict[lang_code])),
                                id="relate_languages.W001"))

    # }}}

    # {{{ check RELATE_SITE_NAME
    try:
        site_name = settings.RELATE_SITE_NAME
        if site_name is None:
            errors.append(
                RelateCriticalCheckMessage(msg=("%s must not be None" %
                                                RELATE_SITE_NAME),
                                           id="relate_site_name.E002"))
        else:
            if not isinstance(site_name, six.string_types):
                errors.append(
                    RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                        "location":
                        "%s/%s" %
                        (RELATE_SITE_NAME, RELATE_CUTOMIZED_SITE_NAME),
                        "types":
                        "string"
                    }),
                                               id="relate_site_name.E003"))
            elif not site_name.strip():
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%s must not be an empty string" %
                             RELATE_SITE_NAME),
                        id="relate_site_name.E004"))
    except AttributeError:
        # This happens when RELATE_SITE_NAME is DELETED from settings.
        errors.append(
            RelateCriticalCheckMessage(msg=(REQUIRED_CONF_ERROR_PATTERN % {
                "location": RELATE_SITE_NAME
            }),
                                       id="relate_site_name.E001"))
    # }}}

    # {{{ check RELATE_OVERRIDE_TEMPLATES_DIRS

    relate_override_templates_dirs = getattr(settings,
                                             RELATE_OVERRIDE_TEMPLATES_DIRS,
                                             None)
    if relate_override_templates_dirs is not None:
        if (isinstance(relate_override_templates_dirs, six.string_types)
                or not is_iterable(relate_override_templates_dirs)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_OVERRIDE_TEMPLATES_DIRS,
                        "types": "an iterable (e.g., a list or tuple)."
                    }),
                    id="relate_override_templates_dirs.E001"))
        else:
            if any(not isinstance(directory, six.string_types)
                   for directory in relate_override_templates_dirs):
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("'%s' must contain only string of paths." %
                             RELATE_OVERRIDE_TEMPLATES_DIRS),
                        id="relate_override_templates_dirs.E002"))
            else:
                for directory in relate_override_templates_dirs:
                    if not os.path.isdir(directory):
                        errors.append(
                            Warning(msg=(
                                "Invalid Templates Dirs item '%s' in '%s', "
                                "it will be ignored." %
                                (directory, RELATE_OVERRIDE_TEMPLATES_DIRS)),
                                    id="relate_override_templates_dirs.W001"))

    # }}}

    # {{{ check RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE
    relate_custom_page_types_removed_deadline = getattr(
        settings, RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE, None)
    if relate_custom_page_types_removed_deadline is not None:
        from datetime import datetime
        if not isinstance(relate_custom_page_types_removed_deadline, datetime):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE,
                        "types": "datetime.datetime"
                    }),
                    id="relate_custom_page_types_removed_deadline.E001"))

    # }}}
    return errors
Beispiel #51
0
        """
        Render the specified template and context. Cache the template object
        in render_context to avoid reparsing and loading when used in a for
        loop.
        """
        resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
        _dict = self.func(*resolved_args, **resolved_kwargs)

        t = context.render_context.get(self)
        if t is None:
            if isinstance(self.filename, Template):
                t = self.filename
            elif isinstance(getattr(self.filename, 'template', None), Template):
                t = self.filename.template
<<<<<<< HEAD
            elif not isinstance(self.filename, six.string_types) and is_iterable(self.filename):
=======
            elif not isinstance(self.filename, str) and is_iterable(self.filename):
>>>>>>> 37c99181c9a6b95433d60f8c8ef9af5731096435
                t = context.template.engine.select_template(self.filename)
            else:
                t = context.template.engine.get_template(self.filename)
            context.render_context[self] = t
        new_context = context.new(_dict)
        # Copy across the CSRF token, if present, because inclusion tags are
        # often used for forms, and we need instructions for using CSRF
        # protection to be as simple as possible.
        csrf_token = context.get('csrf_token')
        if csrf_token is not None:
            new_context['csrf_token'] = csrf_token
        return t.render(new_context)
Beispiel #52
0
    async def prefetch(self, instance_or_list, *fields):
        """
        await orm.prefetch(instance, 'field', 'field', ...)
        await orm.prefetch([instance, instance], 'field', 'field', ...)
        """
        if is_iterable(instance_or_list):
            if not instance_or_list:
                return
            lst = list(instance_or_list)
            model_class = lst[0].__class__
            if any(not isinstance(instance, model_class) for instance in lst):
                raise ValueError(instance_or_list)
        else:
            if not instance_or_list:
                raise ValueError(instance_or_list)
            lst = [instance_or_list]
            model_class = instance_or_list.__class__
        fields = list(fields)
        model_fields = self._fields(model_class, one_to_one=True)
        for f in model_fields:
            if not f.is_relation or f.name not in fields:
                continue
            fields.remove(f.name)
            if hasattr(f, 'attname'):
                related_ids = {
                    getattr(instance, f.attname)
                    for instance in lst
                    if not self.has_prefetched(instance, f.name)
                    and getattr(instance, f.attname)
                }
                if not related_ids:
                    continue
                logger.debug(
                    'leoorm.prefetch: %s from %s: %s',
                    f.name,
                    f.related_model.__qualname__,
                    related_ids,
                )
                related_objects = {
                    instance.pk: instance
                    for instance in await self.get_list(
                        f.related_model, '''
                        SELECT * FROM {db_table} WHERE {pk} = ANY($1)
                    '''.format(
                            db_table=self.db_table(f.related_model),
                            pk=self.pk(f.related_model),
                        ), related_ids)
                }
                for instance in lst:
                    val = getattr(instance, f.attname)
                    if val and val in related_objects:
                        self.set_prefetched(instance, f.name,
                                            related_objects[val])  # noqa
                    elif not self.has_prefetched(instance, f.name):
                        self.set_prefetched(instance, f.name, None)
            else:
                one2one_ids = {
                    instance.pk
                    for instance in lst if
                    not self.has_prefetched(instance, f.name) and instance.pk
                }
                logger.debug(
                    'leoorm.prefetch: %s from %s: %s',
                    f.name,
                    f.related_model.__qualname__,
                    one2one_ids,
                )
                if not one2one_ids:
                    continue
                one2one_objects = {
                    getattr(instance, f.field.column): instance
                    for instance in await self.get_list(
                        f.related_model, **
                        {f.field.column + '__in': one2one_ids})
                }
                for instance in lst:
                    val = one2one_objects.get(instance.pk)
                    self.set_prefetched(instance, f.name, val)

        if fields:
            raise ValueError('Incorrect fields: {}. Allowed: {}'.format(
                fields, ', '.join(f.name for f in model_fields)))
Beispiel #53
0
 def has_perms(self, perm_list, obj=None):
     if not is_iterable(perm_list) or isinstance(perm_list, str):
         raise ValueError('perm_list must be an iterable of permissions.')
     return all(self.has_perm(perm, obj) for perm in perm_list)