Exemple #1
0
 def get_content_type(self, obj=None, id=None, using=None):
     # Convenience function using get_model avoids a circular import when
     # using this model
     ContentType = get_model("contenttypes", "contenttype")
     if obj:
         return ContentType.objects.db_manager(obj._state.db).get_for_model(obj)
     elif id:
         return ContentType.objects.db_manager(using).get_for_id(id)
     else:
         # This should never happen. I love comments like this, don't you?
         raise Exception("Impossible arguments to GFK.get_content_type!")
Exemple #2
0
 def extra_filters(self, pieces, pos, negate):
     """
     Return an extra filter to the queryset so that the results are filtered
     on the appropriate content type.
     """
     if negate:
         return []
     ContentType = get_model("contenttypes", "contenttype")
     content_type = ContentType.objects.get_for_model(self.model)
     prefix = "__".join(pieces[:pos + 1])
     return [("%s__%s" % (prefix, self.content_type_field_name),
         content_type)]
Exemple #3
0
 def test_get_model_only_returns_installed_models(self):
     self.assertEqual(
         get_model("not_installed", "NotInstalledModel"), None)
Exemple #4
0
 def test_get_model_with_not_installed(self):
     self.assertEqual(
         get_model(
             "not_installed", "NotInstalledModel", only_installed=False),
         self.not_installed_module.NotInstalledModel)
Exemple #5
0
    def __new__(cls, name, bases, attrs):
        super_new = super(ModelBase, cls).__new__
        # six.with_metaclass() inserts an extra class called 'NewBase' in the
        # inheritance tree: Model -> NewBase -> object. Ignore this class.
        parents = [
            b for b in bases if isinstance(b, ModelBase) and not (b.__name__ == "NewBase" and b.__mro__ == (b, object))
        ]
        if not parents:
            # If this isn't a subclass of Model, don't do anything special.
            return super_new(cls, name, bases, attrs)

        # Create the class.
        module = attrs.pop("__module__")
        new_class = super_new(cls, name, bases, {"__module__": module})
        attr_meta = attrs.pop("Meta", None)
        abstract = getattr(attr_meta, "abstract", False)
        if not attr_meta:
            meta = getattr(new_class, "Meta", None)
        else:
            meta = attr_meta
        base_meta = getattr(new_class, "_meta", None)

        if getattr(meta, "app_label", None) is None:
            # Figure out the app_label by looking one level up.
            # For 'djangocg.contrib.sites.models', this would be 'sites'.
            model_module = sys.modules[new_class.__module__]
            kwargs = {"app_label": model_module.__name__.split(".")[-2]}
        else:
            kwargs = {}

        new_class.add_to_class("_meta", Options(meta, **kwargs))
        if not abstract:
            new_class.add_to_class(
                "DoesNotExist",
                subclass_exception(
                    str("DoesNotExist"),
                    tuple(x.DoesNotExist for x in parents if hasattr(x, "_meta") and not x._meta.abstract)
                    or (ObjectDoesNotExist,),
                    module,
                    attached_to=new_class,
                ),
            )
            new_class.add_to_class(
                "MultipleObjectsReturned",
                subclass_exception(
                    str("MultipleObjectsReturned"),
                    tuple(x.MultipleObjectsReturned for x in parents if hasattr(x, "_meta") and not x._meta.abstract)
                    or (MultipleObjectsReturned,),
                    module,
                    attached_to=new_class,
                ),
            )
            if base_meta and not base_meta.abstract:
                # Non-abstract child classes inherit some attributes from their
                # non-abstract parent (unless an ABC comes before it in the
                # method resolution order).
                if not hasattr(meta, "ordering"):
                    new_class._meta.ordering = base_meta.ordering
                if not hasattr(meta, "get_latest_by"):
                    new_class._meta.get_latest_by = base_meta.get_latest_by

        is_proxy = new_class._meta.proxy

        if getattr(new_class, "_default_manager", None):
            if not is_proxy:
                # Multi-table inheritance doesn't inherit default manager from
                # parents.
                new_class._default_manager = None
                new_class._base_manager = None
            else:
                # Proxy classes do inherit parent's default manager, if none is
                # set explicitly.
                new_class._default_manager = new_class._default_manager._copy_to_model(new_class)
                new_class._base_manager = new_class._base_manager._copy_to_model(new_class)

        # Bail out early if we have already created this class.
        m = get_model(new_class._meta.app_label, name, seed_cache=False, only_installed=False)
        if m is not None:
            return m

        # Add all attributes to the class.
        for obj_name, obj in attrs.items():
            new_class.add_to_class(obj_name, obj)

        # All the fields of any type declared on this model
        new_fields = new_class._meta.local_fields + new_class._meta.local_many_to_many + new_class._meta.virtual_fields
        field_names = set([f.name for f in new_fields])

        # Basic setup for proxy models.
        if is_proxy:
            base = None
            for parent in [cls for cls in parents if hasattr(cls, "_meta")]:
                if parent._meta.abstract:
                    if parent._meta.fields:
                        raise TypeError(
                            "Abstract base class containing model fields not permitted for proxy model '%s'." % name
                        )
                    else:
                        continue
                if base is not None:
                    raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
                else:
                    base = parent
            if base is None:
                raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
            if new_class._meta.local_fields or new_class._meta.local_many_to_many:
                raise FieldError("Proxy model '%s' contains model fields." % name)
            new_class._meta.setup_proxy(base)
            new_class._meta.concrete_model = base._meta.concrete_model
        else:
            new_class._meta.concrete_model = new_class

        # Do the appropriate setup for any model parents.
        o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields if isinstance(f, OneToOneField)])

        for base in parents:
            original_base = base
            if not hasattr(base, "_meta"):
                # Things without _meta aren't functional models, so they're
                # uninteresting parents.
                continue

            parent_fields = base._meta.local_fields + base._meta.local_many_to_many
            # Check for clashes between locally declared fields and those
            # on the base classes (we cannot handle shadowed fields at the
            # moment).
            for field in parent_fields:
                if field.name in field_names:
                    raise FieldError(
                        "Local field %r in class %r clashes "
                        "with field of similar name from "
                        "base class %r" % (field.name, name, base.__name__)
                    )
            if not base._meta.abstract:
                # Concrete classes...
                base = base._meta.concrete_model
                if base in o2o_map:
                    field = o2o_map[base]
                elif not is_proxy:
                    attr_name = "%s_ptr" % base._meta.module_name
                    field = OneToOneField(base, name=attr_name, auto_created=True, parent_link=True)
                    new_class.add_to_class(attr_name, field)
                else:
                    field = None
                new_class._meta.parents[base] = field
            else:
                # .. and abstract ones.
                for field in parent_fields:
                    new_class.add_to_class(field.name, copy.deepcopy(field))

                # Pass any non-abstract parent classes onto child.
                new_class._meta.parents.update(base._meta.parents)

            # Inherit managers from the abstract base classes.
            new_class.copy_managers(base._meta.abstract_managers)

            # Proxy models inherit the non-abstract managers from their base,
            # unless they have redefined any of them.
            if is_proxy:
                new_class.copy_managers(original_base._meta.concrete_managers)

            # Inherit virtual fields (like GenericForeignKey) from the parent
            # class
            for field in base._meta.virtual_fields:
                if base._meta.abstract and field.name in field_names:
                    raise FieldError(
                        "Local field %r in class %r clashes "
                        "with field of similar name from "
                        "abstract base class %r" % (field.name, name, base.__name__)
                    )
                new_class.add_to_class(field.name, copy.deepcopy(field))

        if abstract:
            # Abstract base models can't be instantiated and don't appear in
            # the list of models for an app. We do the final setup for them a
            # little differently from normal models.
            attr_meta.abstract = False
            new_class.Meta = attr_meta
            return new_class

        new_class._prepare()
        register_models(new_class._meta.app_label, new_class)

        # Because of the way imports happen (recursively), we may or may not be
        # the first time this model tries to register with the framework. There
        # should only be one class for each model, so we always return the
        # registered version.
        return get_model(new_class._meta.app_label, name, seed_cache=False, only_installed=False)