class DisplayOptions(object): def __init__(self, meta): self.meta = meta self.local_fields = [] self.ordering = [] self.template_name = OrderedSet() self.structural_name = [] self.concrete_model = None self.parents = OrderedDict() def contribute_to_class(self, cls, name): cls._meta = self if self.meta: meta_attrs = self.meta.__dict__.copy() for name in self.meta.__dict__: if name.startswith("_"): del meta_attrs[name] # special case template_name because it's an orderedset if "template_name" in meta_attrs: template_names = meta_attrs.pop("template_name") elif hasattr(self.meta, "template_name"): template_names = self.meta.template_name if isinstance(template_names, (list, tuple, OrderedSet, set)): self.template_name.update(template_names) else: self.template_name.add(template_names) for attr_name in DEFAULT_NAMES: if attr_name in meta_attrs: setattr(self, attr_name, meta_attrs.pop(attr_name)) elif hasattr(self.meta, attr_name): setattr(self, attr_name, getattr(self.meta, attr_name)) if meta_attrs != {}: raise TypeError("'class Meta' got invalid attribute(s): {}".format(",".join(meta_attrs.keys()))) del self.meta def add_field(self, field): self.local_fields.insert(bisect(self.local_fields, field), field) if hasattr(self, "_field_cache"): del self._field_name_cache del self._field_cache def _prepare(self, model): pass @property def fields(self): try: self._field_name_cache except AttributeError: self._fill_fields_cache() return self._field_name_cache def get_fields_with_model(self): try: self.field_cache except AttributeError: self._fill_fields_cache() return self.field_cache def _fill_fields_cache(self): cache = [] for parent in self.parents: for field, model in parent._meta.get_fields_with_model(): if model: cache.append((field, model)) else: cache.append((field, parent)) cache.extend(((f, None) for f in self.local_fields)) self.field_cache = tuple(cache) self._field_name_cache = [x for x, _ in cache]