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 []
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()
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)
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)
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)
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)
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)
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()
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)
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
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
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]
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()
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))
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
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 ])
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)
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)
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
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()
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))
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))
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
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
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, }
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))
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))
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)
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()
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 []
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
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)
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)
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)
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)
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
""" 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)
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)))
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)